diff options
608 files changed, 146272 insertions, 30875 deletions
@@ -318,6 +318,29 @@ Other contributions Chris Gray - (retired) Johannes Schickel + Translations + ------------ + Thierry Crozat - Translation Lead + + Catalan: + Jordi Vilalta Prat + + French: + Thierry Crozat + + German: + Simon Sawatzki + Lothar Serra Mari + + Hungarian: + Alex Bevilacqua + + Italian: + Matteo Angelino + + Russian: + Eugene Sandulenko + Websites (design) ----------------- Dobo Balazs - Website design @@ -395,7 +418,7 @@ Other contributions Ravi I. - SCI0 sound resource specification Ruediger Hanke - Port to the MorphOS platform Rune Orsval - Configuration file editor - Rickard Lind - MT32->GM MIDI mapping magic, sound research + Rickard Lind - MT-32->GM MIDI mapping magic, sound research Rink Springer - Port to the DOS platform, several bug fixes Robey Pointer - Bug tracking system hosting Sergey Lapin - Port of Carl's type 2 decompression code @@ -25,7 +25,7 @@ ifeq "$(HAVE_GCC)" "1" # Turn off some annoying and not-so-useful warnings CXXFLAGS+= -Wno-long-long -Wno-multichar -Wno-unknown-pragmas -Wno-reorder # Enable even more warnings... - CXXFLAGS+= -Wpointer-arith -Wcast-qual -Wcast-align + CXXFLAGS+= -Wpointer-arith -Wcast-qual CXXFLAGS+= -Wshadow -Wimplicit -Wnon-virtual-dtor -Wwrite-strings # Currently we disable this gcc flag, since it will also warn in cases, diff --git a/Makefile.common b/Makefile.common index 20be8e1bf6..e2f14810b2 100644 --- a/Makefile.common +++ b/Makefile.common @@ -28,6 +28,7 @@ MODULES += \ engines \ graphics \ common \ + po ifdef USE_MT32EMU MODULES += sound/softsynth/mt32 @@ -8,11 +8,36 @@ For a more comprehensive changelog for the latest experimental SVN code, see: General: - Switched to the "fast" DOSBox OPL emulator. - Fixed a crash in the rjp1 player code affecting the FOTAQ Amiga version. + - Added support for more original media layouts. + - Added support for GUI localization. + - Improved GUI by adding tooltips and radiobuttons. + - Improved GUI usability by hiding more irrelevant options not supported by + specific games. + + AGI: + - Fixed number of GFX glitches. + - Made PIC drawing code picture perfect. + - Added support of MIDI devices. + - Added support for accurate Tandy sound emulation. Switched to it as default. + + Drascula: + - Fixed number of GFX glitches. + - Made many cutscenes smoother. + - Changed behavior of items menu. Now it shows up on mouse up. Groovie: - Added support for the Macintosh version of The 7th Guest. - Added support for custom MT-32 instruments. + Parallaction: + - Made part one of The Big Red Adventure completable. + + SAGA: + - Fixed graphics glitches in several scenes. + + SCUMM: + - Several improvements in Maniac Mansion NES. + PSP port: - Switched to new backend design which fixes minor graphical issues, speeds things up, and provides 16-bit support. diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp index 96def04e25..df9efe54b1 100644 --- a/backends/events/sdl/sdl-events.cpp +++ b/backends/events/sdl/sdl-events.cpp @@ -213,6 +213,7 @@ bool SdlEventManager::pollSdlEvent(Common::Event &event) { } SDL_Event ev; + ev.type = SDL_NOEVENT; while (SDL_PollEvent(&ev)) { preprocessEvents(&ev); if (dispatchSDLEvent(ev, event)) diff --git a/backends/events/symbiansdl/symbiansdl-events.cpp b/backends/events/symbiansdl/symbiansdl-events.cpp index af57e81ccc..2d144f9ad9 100644 --- a/backends/events/symbiansdl/symbiansdl-events.cpp +++ b/backends/events/symbiansdl/symbiansdl-events.cpp @@ -28,6 +28,7 @@ #include "backends/events/symbiansdl/symbiansdl-events.h" #include "backends/platform/symbian/src/SymbianActions.h" #include "gui/message.h" +#include "common/translation.h" #include <bautils.h> @@ -183,7 +184,7 @@ bool SymbianSdlEventManager::remapKey(SDL_Event &ev, Common::Event &event) { case GUI::ACTION_QUIT: { - GUI::MessageDialog alert("Do you want to quit ?", "Yes", "No"); + GUI::MessageDialog alert(_("Do you want to quit ?"), _("Yes"), _("No")); if (alert.runModal() == GUI::kMessageOK) g_system->quit(); diff --git a/backends/fs/amigaos4/amigaos4-fs.cpp b/backends/fs/amigaos4/amigaos4-fs.cpp index fe6164cb0c..8a57a3cf1c 100644 --- a/backends/fs/amigaos4/amigaos4-fs.cpp +++ b/backends/fs/amigaos4/amigaos4-fs.cpp @@ -368,7 +368,7 @@ bool AmigaOSFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, b } if (ERROR_NO_MORE_ENTRIES != IDOS->IoErr() ) { - debug(6, "An error occured during ExamineDir"); + debug(6, "An error occurred during ExamineDir"); ret = false; } else { ret = true; diff --git a/backends/fs/ds/ds-fs-factory.cpp b/backends/fs/ds/ds-fs-factory.cpp index 0dfa70b716..4919c04174 100644 --- a/backends/fs/ds/ds-fs-factory.cpp +++ b/backends/fs/ds/ds-fs-factory.cpp @@ -27,7 +27,7 @@ #include "backends/fs/ds/ds-fs.h" #include "dsmain.h" //for the isGBAMPAvailable() function -DECLARE_SINGLETON(DSFilesystemFactory); +DECLARE_SINGLETON(DSFilesystemFactory) AbstractFSNode *DSFilesystemFactory::makeRootFileNode() const { if (DS::isGBAMPAvailable()) { diff --git a/backends/fs/ds/ds-fs.cpp b/backends/fs/ds/ds-fs.cpp index 6fc2894925..675084ff56 100644 --- a/backends/fs/ds/ds-fs.cpp +++ b/backends/fs/ds/ds-fs.cpp @@ -8,15 +8,18 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ @@ -115,7 +118,7 @@ DSFileSystemNode::DSFileSystemNode(const Common::String& path, bool isDir) { // consolePrintf("Found: %d, Dir: %d\n", _isValid, _isDirectory); } -DSFileSystemNode::DSFileSystemNode(const DSFileSystemNode* node) { +DSFileSystemNode::DSFileSystemNode(const DSFileSystemNode *node) { //TODO: not implemented? } @@ -144,7 +147,7 @@ bool DSFileSystemNode::getChildren(AbstractFSList &dirList, ListMode mode, bool _zipFile->changeToRoot(); /* // This is the root dir, so add the RAM folder - DSFileSystemNode* dsfsn = new DSFileSystemNode("ds:/ram"); + DSFileSystemNode *dsfsn = new DSFileSystemNode("ds:/ram"); dsfsn->_isDirectory = true; dirList->push_back(wrap(dsfsn)); */ @@ -162,7 +165,7 @@ bool DSFileSystemNode::getChildren(AbstractFSList &dirList, ListMode mode, bool if ( (_zipFile->isDirectory() && ((mode == Common::FSNode::kListDirectoriesOnly) || (mode == Common::FSNode::kListAll)) ) || (!_zipFile->isDirectory() && ((mode == Common::FSNode::kListFilesOnly) || (mode == Common::FSNode::kListAll)) ) ) { - DSFileSystemNode* dsfsn = new DSFileSystemNode("ds:/" + Common::String(n), _zipFile->isDirectory()); + DSFileSystemNode *dsfsn = new DSFileSystemNode("ds:/" + Common::String(n), _zipFile->isDirectory()); dsfsn->_isDirectory = _zipFile->isDirectory(); dirList.push_back((dsfsn)); } @@ -173,15 +176,15 @@ bool DSFileSystemNode::getChildren(AbstractFSList &dirList, ListMode mode, bool return true; } -AbstractFSNode* DSFileSystemNode::getParent() const { +AbstractFSNode *DSFileSystemNode::getParent() const { // consolePrintf("parent\n"); DSFileSystemNode *p; if (_path != "ds:/") { - char *path = (char *) _path.c_str(); + const char *path = (const char *)_path.c_str(); int lastSlash = 4; - for (int r = 4; r < (int) _path.size(); r++) { + for (uint r = 4; r < _path.size(); r++) { if (path[r] == '\\') { lastSlash = r; } @@ -259,7 +262,7 @@ GBAMPFileSystemNode::GBAMPFileSystemNode(const Common::String& path) { _path = path; } -GBAMPFileSystemNode::GBAMPFileSystemNode(const Common::String& path, bool isDirectory) { +GBAMPFileSystemNode::GBAMPFileSystemNode(const Common::String& path, bool isDir) { //consolePrintf("'%s'",path.c_str()); int lastSlash = 3; @@ -272,11 +275,11 @@ GBAMPFileSystemNode::GBAMPFileSystemNode(const Common::String& path, bool isDire _displayName = Common::String(path.c_str() + lastSlash + 1); _path = path; _isValid = true; - _isDirectory = isDirectory; + _isDirectory = isDir; } -GBAMPFileSystemNode::GBAMPFileSystemNode(const GBAMPFileSystemNode* node) { +GBAMPFileSystemNode::GBAMPFileSystemNode(const GBAMPFileSystemNode *node) { //TODO: not implemented? } @@ -319,7 +322,7 @@ bool GBAMPFileSystemNode::getChildren(AbstractFSList& dirList, ListMode mode, bo if ( ((entryType == TYPE_DIR) && ((mode == Common::FSNode::kListDirectoriesOnly) || (mode == Common::FSNode::kListAll))) || ((entryType == TYPE_FILE) && ((mode == Common::FSNode::kListFilesOnly) || (mode == Common::FSNode::kListAll))) ) { - GBAMPFileSystemNode* dsfsn; + GBAMPFileSystemNode *dsfsn; //consolePrintf("Fname: %s\n", fname); @@ -348,15 +351,15 @@ bool GBAMPFileSystemNode::getChildren(AbstractFSList& dirList, ListMode mode, bo return true; } -AbstractFSNode* GBAMPFileSystemNode::getParent() const { +AbstractFSNode *GBAMPFileSystemNode::getParent() const { // consolePrintf("parent\n"); GBAMPFileSystemNode *p; if (_path != "mp:/") { - char *path = (char *) _path.c_str(); + const char *path = (const char *)_path.c_str(); int lastSlash = 4; - for (int r = 4; r < (int) strlen((char *) path); r++) { + for (uint r = 4; r < strlen(path); r++) { if (path[r] == '/') { lastSlash = r; } @@ -413,18 +416,12 @@ bool DSFileStream::eos() const { } int32 DSFileStream::pos() const { - if (_writeBufferPos > 0) { - // Discard constness. Bad, but I can't see another way. - ((DSFileStream *) (this))->flush(); - } + assert(_writeBufferPos == 0); // This method may only be called when reading! return std_ftell((FILE *)_handle); } int32 DSFileStream::size() const { - if (_writeBufferPos > 0) { - // Discard constness. Bad, but I can't see another way. - ((DSFileStream *) (this))->flush(); - } + assert(_writeBufferPos == 0); // This method may only be called when reading! int32 oldPos = std_ftell((FILE *)_handle); std_fseek((FILE *)_handle, 0, SEEK_END); int32 length = std_ftell((FILE *)_handle); @@ -444,16 +441,15 @@ uint32 DSFileStream::read(void *ptr, uint32 len) { if (_writeBufferPos > 0) { flush(); } - return std_fread((byte *)ptr, 1, len, (FILE *)_handle); + return std_fread(ptr, 1, len, (FILE *)_handle); } uint32 DSFileStream::write(const void *ptr, uint32 len) { if (_writeBufferPos + len < WRITE_BUFFER_SIZE) { memcpy(_writeBuffer + _writeBufferPos, ptr, len); _writeBufferPos += len; - } - else - { + return len; + } else { if (_writeBufferPos > 0) { flush(); } @@ -483,29 +479,31 @@ DSFileStream *DSFileStream::makeFromPath(const Common::String &path, bool writeM // Stdio replacements -#define MAX_FILE_HANDLES 32 +enum { + MAX_FILE_HANDLES = 32 +}; -bool inited = false; -DS::fileHandle handle[MAX_FILE_HANDLES]; +static bool inited = false; +static DS::fileHandle s_handle[MAX_FILE_HANDLES]; -FILE* std_fopen(const char* name, const char* mode) { +FILE *std_fopen(const char *name, const char *mode) { if (!inited) { for (int r = 0; r < MAX_FILE_HANDLES; r++) { - handle[r].used = false; + s_handle[r].used = false; } inited = true; currentDir[0] = '\0'; } - char* realName = (char *) name; + char realName[MAXPATHLEN]; // Remove file system prefix if ((name[0] == 'd') && (name[1] == 's') && (name[2] == ':') && (name[3] == '/')) { - realName += 4; - } - - if ((name[0] == 'm') && (name[1] == 'p') && (name[2] == ':') && (name[3] == '/')) { - realName += 4; + strlcpy(realName, name + 4, MAXPATHLEN); + } else if ((name[0] == 'm') && (name[1] == 'p') && (name[2] == ':') && (name[3] == '/')) { + strlcpy(realName, name + 4, MAXPATHLEN); + } else { + strlcpy(realName, name, MAXPATHLEN); } // consolePrintf("Open file:"); @@ -515,13 +513,14 @@ FILE* std_fopen(const char* name, const char* mode) { FAT_chdir("/"); // Turn all back slashes into forward slashes for gba_nds_fat - char* p = realName; + char *p = realName; while (*p) { - if (*p == '\\') *p = '/'; + if (*p == '\\') + *p = '/'; p++; } - FAT_FILE* result = FAT_fopen(realName, mode); + FAT_FILE *result = FAT_fopen(realName, mode); if (result == 0) { // consolePrintf("Error code %d\n", result); @@ -531,42 +530,21 @@ FILE* std_fopen(const char* name, const char* mode) { } // MT_memoryReport(); - return (FILE *) result; + return (FILE *)result; } // Fail to open file for writing. It's in ROM! // Allocate a file handle int r = 0; - while (handle[r].used) { + while (s_handle[r].used) { r++; assert(r < MAX_FILE_HANDLES); } -#ifdef GBA_SRAM_SAVE - if (strchr(mode, 'w')) { -// consolePrintf("Writing %s\n", realName); - handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, true); - } else { -// consolePrintf("Reading %s\n", realName); - handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, false); - } -#endif - - if (handle[r].sramFile) { - handle[r].used = true; - handle[r].pos = 0; - handle[r].data = NULL; - handle[r].size = handle[r].sramFile->getSize(); -// consolePrintf("Found it"); - return &handle[r]; - } - -// consolePrintf("Not in SRAM!"); - - char* data; + char *data; - ZipFile* zip = DSFileSystemNode::getZip(); + ZipFile *zip = DSFileSystemNode::getZip(); if (!zip) { // consolePrintf("No zip yet!"); return NULL; @@ -578,7 +556,7 @@ FILE* std_fopen(const char* name, const char* mode) { if (currentDir[0] != 0) { char nameWithPath[128]; - sprintf(nameWithPath, "%s\%s", currentDir, realName); + sprintf(nameWithPath, "%s\\%s", currentDir, realName); strcpy(realName, nameWithPath); } @@ -589,17 +567,18 @@ FILE* std_fopen(const char* name, const char* mode) { zip->setAllFilesVisible(false); // Allocate a file handle - int r = 0; - while (handle[r].used) r++; + r = 0; + while (s_handle[r].used) + r++; - handle[r].used = true; - handle[r].pos = 0; - handle[r].data = data; - handle[r].size = zip->getFileSize(); + s_handle[r].used = true; + s_handle[r].pos = 0; + s_handle[r].data = data; + s_handle[r].size = zip->getFileSize(); // consolePrintf("Opened file %d: %s (%s) ", r, realName, name); - return &handle[r]; + return &s_handle[r]; } else { zip->setAllFilesVisible(false); // consolePrintf("Not found: %s (%s) ", realName, name); @@ -607,7 +586,7 @@ FILE* std_fopen(const char* name, const char* mode) { } } -void std_fclose(FILE* handle) { +void std_fclose(FILE *handle) { if (DS::isGBAMPAvailable()) { FAT_fclose((FAT_FILE *) handle); @@ -615,19 +594,15 @@ void std_fclose(FILE* handle) { } handle->used = false; - if (handle->sramFile) { - delete handle->sramFile; - handle->sramFile = NULL; - } } -size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) { +size_t std_fread(void *ptr, size_t size, size_t numItems, FILE *handle) { // consolePrintf("fread %d,%d %d ", size, numItems, ptr); if (DS::isGBAMPAvailable()) { readPastEndOfFile = false; - int bytes = FAT_fread((void *) ptr, size, numItems, (FAT_FILE *) handle); + int bytes = FAT_fread(ptr, size, numItems, (FAT_FILE *) handle); if (!FAT_feof((FAT_FILE *) handle)) { return numItems; } else { @@ -638,36 +613,22 @@ size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) { return numItems; } - if (handle->sramFile) { - int bytes = 0; - int result = 1; - //consolePrintf("fread size=", size * numItems); - for (int r = 0; (r < (s32) size * (s32) numItems) && (result > 0); r++) { - result = handle->sramFile->read((void *) ( ((char *) (ptr)) + r), 1); - bytes += result; - //consolePrintf("'%d',", ((char *) (ptr))[0]); - } - - handle->pos += bytes; - - return bytes / size; - } - - if ((int)(handle->pos + size * numItems) > handle->size) { + if (handle->pos > handle->size) + numItems = 0; + else if ((int)(handle->pos + size * numItems) > handle->size) numItems = (handle->size - handle->pos) / size; - if (numItems < 0) numItems = 0; - } // consolePrintf("read %d ", size * numItems); - memcpy((void *) ptr, handle->data + handle->pos, size * numItems); + memcpy(ptr, handle->data + handle->pos, size * numItems); handle->pos += size * numItems; return numItems; } -size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) { - if ((handle == stdin)) return 0; +size_t std_fwrite(const void *ptr, size_t size, size_t numItems, FILE *handle) { + if ((handle == stdin)) + return 0; if ((handle == stderr) || (handle == stdout)) { // consolePrintf((char *) ptr); @@ -677,7 +638,7 @@ size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) { //consolePrintf("fwrite size=%d\n", size * numItems); if (DS::isGBAMPAvailable()) { - FAT_fwrite(((char *) (ptr)), size, numItems, (FAT_FILE *) handle); + FAT_fwrite(ptr, size, numItems, (FAT_FILE *) handle); return numItems; int length = size * numItems; @@ -694,36 +655,27 @@ size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) { return numItems; } - if (handle->sramFile) { - handle->sramFile->write(ptr, size); - return size; - } else { - return 0; - } + return 0; } -bool std_feof(FILE* handle) { +bool std_feof(FILE *handle) { // consolePrintf("feof "); if (DS::isGBAMPAvailable()) { return readPastEndOfFile && FAT_feof((FAT_FILE *) handle); } - if (handle->sramFile) { - return handle->sramFile->eos(); - } - // consolePrintf("feof %s", handle->pos >= handle->size? "true": "false"); return handle->pos >= handle->size; } -int std_fflush(FILE* handle) { +int std_fflush(FILE *handle) { //FIXME: not implemented? // consolePrintf("fflush "); return 0; } -long int std_ftell(FILE* handle) { +long int std_ftell(FILE *handle) { if (DS::isGBAMPAvailable()) { return FAT_ftell((FAT_FILE *) handle); } @@ -731,7 +683,7 @@ long int std_ftell(FILE* handle) { return handle->pos; } -int std_fseek(FILE* handle, long int offset, int whence) { +int std_fseek(FILE *handle, long int offset, int whence) { // consolePrintf("fseek %d %d ", offset, whence); if (DS::isGBAMPAvailable()) { @@ -756,14 +708,14 @@ int std_fseek(FILE* handle, long int offset, int whence) { return 0; } -int std_ferror(FILE* handle) { +int std_ferror(FILE *handle) { //FIXME: not implemented? // consolePrintf("ferror "); return readPastEndOfFile; } -void std_clearerr(FILE* handle) { +void std_clearerr(FILE *handle) { //FIXME: not implemented? readPastEndOfFile = false; // consolePrintf("clearerr "); diff --git a/backends/fs/ds/ds-fs.h b/backends/fs/ds/ds-fs.h index c8bf7d6cf2..6961022848 100644 --- a/backends/fs/ds/ds-fs.h +++ b/backends/fs/ds/ds-fs.h @@ -8,27 +8,30 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ #ifndef _DS_FS_H #define _DS_FS_H -//#include <NDS/ARM9/console.h> #include "common/fs.h" +#include "common/stream.h" +#include "backends/fs/abstract-fs.h" + #include "zipreader.h" -#include "ramsave.h" #include "fat/gba_nds_fat.h" -#include "backends/fs/abstract-fs.h" namespace DS { @@ -40,7 +43,7 @@ namespace DS { */ class DSFileSystemNode : public AbstractFSNode { protected: - static ZipFile* _zipFile; + static ZipFile *_zipFile; Common::String _displayName; Common::String _path; @@ -96,7 +99,7 @@ public: * Returns the zip file this node points to. * TODO: check this documentation. */ - static ZipFile* getZip() { return _zipFile; } + static ZipFile *getZip() { return _zipFile; } }; /** @@ -161,16 +164,16 @@ public: struct fileHandle { int pos; bool used; - char* data; + char *data; int size; - - DSSaveFile* sramFile; }; class DSFileStream : public Common::SeekableReadStream, public Common::WriteStream, public Common::NonCopyable { protected: - static const int WRITE_BUFFER_SIZE = 512; + enum { + WRITE_BUFFER_SIZE = 512 + }; /** File handle to the actual file. */ void *_handle; @@ -206,24 +209,24 @@ public: #undef stdout #undef stdin -#define stdout ((DS::fileHandle*) -1) -#define stderr ((DS::fileHandle*) -2) -#define stdin ((DS::fileHandle*) -3) +#define stdout ((DS::fileHandle *) -1) +#define stderr ((DS::fileHandle *) -2) +#define stdin ((DS::fileHandle *) -3) #define FILE DS::fileHandle // Please do not remove any of these prototypes that appear not to be required. -FILE* std_fopen(const char* name, const char* mode); -void std_fclose(FILE* handle); -size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle); -size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle); -bool std_feof(FILE* handle); -long int std_ftell(FILE* handle); -int std_fseek(FILE* handle, long int offset, int whence); -void std_clearerr(FILE* handle); -int std_fflush(FILE* handle); -int std_ferror(FILE* handle); - -} //namespace DS +FILE* std_fopen(const char *name, const char *mode); +void std_fclose(FILE *handle); +size_t std_fread(void *ptr, size_t size, size_t numItems, FILE *handle); +size_t std_fwrite(const void *ptr, size_t size, size_t numItems, FILE *handle); +bool std_feof(FILE *handle); +long int std_ftell(FILE *handle); +int std_fseek(FILE *handle, long int offset, int whence); +void std_clearerr(FILE *handle); +int std_fflush(FILE *handle); +int std_ferror(FILE *handle); + +} // End of namespace DS #endif //_DS_FS_H diff --git a/backends/fs/psp/psp-stream.cpp b/backends/fs/psp/psp-stream.cpp index 83ff095aa8..67c73beeaa 100644 --- a/backends/fs/psp/psp-stream.cpp +++ b/backends/fs/psp/psp-stream.cpp @@ -81,10 +81,10 @@ PSPIoStream::PSPIoStream(const Common::String &path, bool writeMode) PSPIoStream::~PSPIoStream() { DEBUG_ENTER_FUNC(); - if (PowerMan.beginCriticalSection() == PowerManager::Blocked) + if (PowerMan.beginCriticalSection()) PSP_DEBUG_PRINT_FUNC("Suspended\n"); - PowerMan.unregisterSuspend(this); // Unregister with powermanager to be suspended + PowerMan.unregisterForSuspend(this); // Unregister with powermanager to be suspended // 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 @@ -100,7 +100,7 @@ PSPIoStream::~PSPIoStream() { */ void *PSPIoStream::open() { DEBUG_ENTER_FUNC(); - if (PowerMan.beginCriticalSection() == PowerManager::Blocked) { + if (PowerMan.beginCriticalSection()) { // No need to open. Just return the _handle resume() already opened. PSP_DEBUG_PRINT_FUNC("Suspended\n"); } @@ -118,7 +118,7 @@ void *PSPIoStream::open() { _cache = (char *)memalign(64, CACHE_SIZE); } - PowerMan.registerSuspend(this); // Register with the powermanager to be suspended + PowerMan.registerForSuspend(this); // Register with the powermanager to be suspended PowerMan.endCriticalSection(); @@ -233,7 +233,7 @@ uint32 PSPIoStream::read(void *ptr, uint32 len) { } } - if (PowerMan.beginCriticalSection() == PowerManager::Blocked) + if (PowerMan.beginCriticalSection()) PSP_DEBUG_PRINT_FUNC("Suspended\n"); @@ -309,7 +309,7 @@ inline bool PSPIoStream::isOffsetInCache(uint32 offset) { uint32 PSPIoStream::write(const void *ptr, uint32 len) { DEBUG_ENTER_FUNC(); // Check if we can access the file - if (PowerMan.beginCriticalSection() == PowerManager::Blocked) + if (PowerMan.beginCriticalSection()) PSP_DEBUG_PRINT_FUNC("Suspended\n"); PSP_DEBUG_PRINT_FUNC("filename[%s], len[0x%x]\n", _path.c_str(), len); @@ -346,7 +346,7 @@ uint32 PSPIoStream::write(const void *ptr, uint32 len) { bool PSPIoStream::flush() { DEBUG_ENTER_FUNC(); // Enter critical section - if (PowerMan.beginCriticalSection() == PowerManager::Blocked) + if (PowerMan.beginCriticalSection()) PSP_DEBUG_PRINT_FUNC("Suspended\n"); int ret = fflush((FILE *)_handle); diff --git a/backends/graphics/graphics.h b/backends/graphics/graphics.h index 0ea425c9bc..9eb354aee4 100644 --- a/backends/graphics/graphics.h +++ b/backends/graphics/graphics.h @@ -48,7 +48,7 @@ public: virtual int getGraphicsMode() const = 0; #ifdef USE_RGB_COLOR virtual Graphics::PixelFormat getScreenFormat() const = 0; - virtual Common::List<Graphics::PixelFormat> getSupportedFormats() = 0; + virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const = 0; #endif virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL) = 0; virtual int getScreenChangeID() const = 0; diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h index f12e4b45d7..17d0b842e9 100644 --- a/backends/graphics/opengl/opengl-graphics.h +++ b/backends/graphics/opengl/opengl-graphics.h @@ -53,7 +53,7 @@ public: virtual int getGraphicsMode() const; #ifdef USE_RGB_COLOR virtual Graphics::PixelFormat getScreenFormat() const; - virtual Common::List<Graphics::PixelFormat> getSupportedFormats() = 0; + virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const = 0; #endif virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL); virtual int getScreenChangeID() const; diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp index 6207561c07..b12c3af5cd 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.cpp +++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp @@ -57,7 +57,7 @@ const Graphics::PixelFormat RGBList[] = { Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0), // RGBA4444 }; -Common::List<Graphics::PixelFormat> OpenGLSdlGraphicsManager::getSupportedFormats() { +Common::List<Graphics::PixelFormat> OpenGLSdlGraphicsManager::getSupportedFormats() const { static Common::List<Graphics::PixelFormat> list; static bool inited = false; diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h index 0f69793c1b..56aae27ab7 100644 --- a/backends/graphics/openglsdl/openglsdl-graphics.h +++ b/backends/graphics/openglsdl/openglsdl-graphics.h @@ -45,7 +45,7 @@ public: virtual void init(); #ifdef USE_RGB_COLOR - virtual Common::List<Graphics::PixelFormat> getSupportedFormats(); + virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const; #endif virtual void warpMouse(int x, int y); diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp index a554479756..e8251a779d 100644 --- a/backends/graphics/sdl/sdl-graphics.cpp +++ b/backends/graphics/sdl/sdl-graphics.cpp @@ -29,6 +29,7 @@ #include "common/system.h" #include "common/config-manager.h" #include "common/mutex.h" +#include "common/translation.h" #include "common/util.h" #ifdef USE_RGB_COLOR #include "common/list.h" @@ -41,7 +42,7 @@ #include "backends/events/sdl/sdl-events.h" static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { - {"1x", "Normal (no scaling)", GFX_NORMAL}, + {"1x", _s("Normal (no scaling)"), GFX_NORMAL}, #ifdef USE_SCALERS {"2x", "2x", GFX_DOUBLESIZE}, {"3x", "3x", GFX_TRIPLESIZE}, @@ -97,11 +98,11 @@ AspectRatio::AspectRatio(int w, int h) { } #if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) && defined(USE_SCALERS) -static const size_t AR_COUNT = 4; -static const char* desiredAspectRatioAsStrings[AR_COUNT] = { "auto", "4/3", "16/9", "16/10" }; -static const AspectRatio desiredAspectRatios[AR_COUNT] = { AspectRatio(0, 0), AspectRatio(4,3), AspectRatio(16,9), AspectRatio(16,10) }; - static AspectRatio getDesiredAspectRatio() { + const size_t AR_COUNT = 4; + const char* desiredAspectRatioAsStrings[AR_COUNT] = { "auto", "4/3", "16/9", "16/10" }; + const AspectRatio desiredAspectRatios[AR_COUNT] = { AspectRatio(0, 0), AspectRatio(4,3), AspectRatio(16,9), AspectRatio(16,10) }; + //TODO : We could parse an arbitrary string, if we code enough proper validation Common::String desiredAspectRatio = ConfMan.get("desired_screen_aspect_ratio"); @@ -359,45 +360,53 @@ OSystem::TransactionError SdlGraphicsManager::endGFXTransaction() { } #ifdef USE_RGB_COLOR -const Graphics::PixelFormat RGBList[] = { +Common::List<Graphics::PixelFormat> SdlGraphicsManager::getSupportedFormats() const { + assert(!_supportedFormats.empty()); + return _supportedFormats; +} + +void SdlGraphicsManager::detectSupportedFormats() { + + // Clear old list + _supportedFormats.clear(); + + // Some tables with standard formats that we always list + // as "supported". If frontend code tries to use one of + // these, we will perform the necessary format + // conversion in the background. Of course this incurs a + // performance hit, but on desktop ports this should not + // matter. We still push the currently active format to + // the front, so if frontend code just uses the first + // available format, it will get one that is "cheap" to + // use. + const Graphics::PixelFormat RGBList[] = { #ifdef ENABLE_32BIT - // RGBA8888, ARGB8888, RGB888 - Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0), - Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24), - Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0), + // RGBA8888, ARGB8888, RGB888 + Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0), + Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24), + Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0), #endif - // RGB565, XRGB1555, RGB555, RGBA4444, ARGB4444 - Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), - Graphics::PixelFormat(2, 5, 5, 5, 1, 10, 5, 0, 15), - Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0), - Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0), - Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12) -}; -const Graphics::PixelFormat BGRList[] = { + // RGB565, XRGB1555, RGB555, RGBA4444, ARGB4444 + Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0), + Graphics::PixelFormat(2, 5, 5, 5, 1, 10, 5, 0, 15), + Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0), + Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0), + Graphics::PixelFormat(2, 4, 4, 4, 4, 8, 4, 0, 12) + }; + const Graphics::PixelFormat BGRList[] = { #ifdef ENABLE_32BIT - // ABGR8888, BGRA8888, BGR888 - Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24), - Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0), - Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0), + // ABGR8888, BGRA8888, BGR888 + Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24), + Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0), + Graphics::PixelFormat(3, 8, 8, 8, 0, 0, 8, 16, 0), #endif - // BGR565, XBGR1555, BGR555, ABGR4444, BGRA4444 - Graphics::PixelFormat(2, 5, 6, 5, 0, 0, 5, 11, 0), - Graphics::PixelFormat(2, 5, 5, 5, 1, 0, 5, 10, 15), - Graphics::PixelFormat(2, 5, 5, 5, 0, 0, 5, 10, 0), - Graphics::PixelFormat(2, 4, 4, 4, 4, 0, 4, 8, 12), - Graphics::PixelFormat(2, 4, 4, 4, 4, 4, 8, 12, 0) -}; - -// TODO: prioritize matching alpha masks -Common::List<Graphics::PixelFormat> SdlGraphicsManager::getSupportedFormats() { - static Common::List<Graphics::PixelFormat> list; - static bool inited = false; - - if (inited) - return list; - - bool BGR = false; - int listLength = ARRAYSIZE(RGBList); + // BGR565, XBGR1555, BGR555, ABGR4444, BGRA4444 + Graphics::PixelFormat(2, 5, 6, 5, 0, 0, 5, 11, 0), + Graphics::PixelFormat(2, 5, 5, 5, 1, 0, 5, 10, 15), + Graphics::PixelFormat(2, 5, 5, 5, 0, 0, 5, 10, 0), + Graphics::PixelFormat(2, 4, 4, 4, 4, 0, 4, 8, 12), + Graphics::PixelFormat(2, 4, 4, 4, 4, 4, 8, 12, 0) + }; Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8(); if (_hwscreen) { @@ -413,30 +422,30 @@ Common::List<Graphics::PixelFormat> SdlGraphicsManager::getSupportedFormats() { format.aLoss = 8; // Push it first, as the prefered format. - list.push_back(format); + _supportedFormats.push_back(format); + } - if (format.bShift > format.rShift) - BGR = true; + // TODO: prioritize matching alpha masks + int i; - // Mark that we don't need to do this any more. - inited = true; + // Push some RGB formats + for (i = 0; i < ARRAYSIZE(RGBList); i++) { + if (_hwscreen && (RGBList[i].bytesPerPixel > format.bytesPerPixel)) + continue; + if (RGBList[i] != format) + _supportedFormats.push_back(RGBList[i]); } - for (int i = 0; i < listLength; i++) { - if (inited && (RGBList[i].bytesPerPixel > format.bytesPerPixel)) + // Push some BGR formats + for (i = 0; i < ARRAYSIZE(BGRList); i++) { + if (_hwscreen && (BGRList[i].bytesPerPixel > format.bytesPerPixel)) continue; - if (BGR) { - if (BGRList[i] != format) - list.push_back(BGRList[i]); - list.push_back(RGBList[i]); - } else { - if (RGBList[i] != format) - list.push_back(RGBList[i]); - list.push_back(BGRList[i]); - } + if (BGRList[i] != format) + _supportedFormats.push_back(BGRList[i]); } - list.push_back(Graphics::PixelFormat::createFormatCLUT8()); - return list; + + // Finally, we always supposed 8 bit palette graphics + _supportedFormats.push_back(Graphics::PixelFormat::createFormatCLUT8()); } #endif @@ -718,6 +727,10 @@ bool SdlGraphicsManager::loadGFXMode() { _hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16, _videoMode.fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE ); +#ifdef USE_RGB_COLOR + detectSupportedFormats(); +#endif + if (_hwscreen == NULL) { // DON'T use error(), as this tries to bring up the debug // console, which WON'T WORK now that _hwscreen is hosed. @@ -1531,6 +1544,10 @@ void SdlGraphicsManager::setMousePos(int x, int y) { void SdlGraphicsManager::warpMouse(int x, int y) { int y1 = y; + // Don't change mouse position, when mouse is outside of our window (in case of windowed mode) + if (!(SDL_GetAppState( ) & SDL_APPMOUSEFOCUS)) + return; + if (_videoMode.aspectRatioCorrection && !_overlayVisible) y1 = real2Aspect(y); diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h index 4ca92e9d30..0218be55dc 100644 --- a/backends/graphics/sdl/sdl-graphics.h +++ b/backends/graphics/sdl/sdl-graphics.h @@ -87,7 +87,7 @@ public: virtual int getGraphicsMode() const; #ifdef USE_RGB_COLOR virtual Graphics::PixelFormat getScreenFormat() const { return _screenFormat; } - virtual Common::List<Graphics::PixelFormat> getSupportedFormats(); + virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const; #endif virtual void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL); virtual int getScreenChangeID() const { return _screenChangeCount; } @@ -160,6 +160,13 @@ protected: #ifdef USE_RGB_COLOR Graphics::PixelFormat _screenFormat; Graphics::PixelFormat _cursorFormat; + Common::List<Graphics::PixelFormat> _supportedFormats; + + /** + * Update the list of supported pixel formats. + * This method is invoked by loadGFXMode(). + */ + void detectSupportedFormats(); #endif /** Temporary screen (for scalers) */ diff --git a/backends/keymapper/remap-dialog.cpp b/backends/keymapper/remap-dialog.cpp index fd90b67d60..067d8453a5 100644 --- a/backends/keymapper/remap-dialog.cpp +++ b/backends/keymapper/remap-dialog.cpp @@ -31,6 +31,8 @@ #include "gui/ScrollBarWidget.h" #include "gui/ThemeEval.h" +#include "common/translation.h" + namespace Common { enum { @@ -44,12 +46,12 @@ RemapDialog::RemapDialog() _keymapper = g_system->getEventManager()->getKeymapper(); assert(_keymapper); - _kmPopUpDesc = new GUI::StaticTextWidget(this, "KeyMapper.PopupDesc", "Keymap:"); + _kmPopUpDesc = new GUI::StaticTextWidget(this, "KeyMapper.PopupDesc", _("Keymap:")); _kmPopUp = new GUI::PopUpWidget(this, "KeyMapper.Popup"); _scrollBar = new GUI::ScrollBarWidget(this, 0, 0, 0, 0); - new GUI::ButtonWidget(this, "KeyMapper.Close", "Close", kCloseCmd); + new GUI::ButtonWidget(this, "KeyMapper.Close", _("Close"), 0, kCloseCmd); } RemapDialog::~RemapDialog() { @@ -61,7 +63,7 @@ void RemapDialog::open() { const Stack<Keymapper::MapRecord> &activeKeymaps = _keymapper->getActiveStack(); if (!(activeKeymaps.size() > 0)) { - _kmPopUp->appendEntry(activeKeymaps.top().keymap->getName() + " (Active)"); + _kmPopUp->appendEntry(activeKeymaps.top().keymap->getName() + _(" (Active)")); divider = true; } @@ -95,7 +97,7 @@ void RemapDialog::open() { if (divider) _kmPopUp->appendEntry(""); for (it = _globalKeymaps->begin(); it != _globalKeymaps->end(); ++it) { - _kmPopUp->appendEntry(it->_value->getName() + " (Global)", idx); + _kmPopUp->appendEntry(it->_value->getName() + _(" (Global)"), idx); _keymapTable[idx++] = it->_value; } divider = true; @@ -105,7 +107,7 @@ void RemapDialog::open() { if (divider) _kmPopUp->appendEntry(""); for (it = _gameKeymaps->begin(); it != _gameKeymaps->end(); ++it) { - _kmPopUp->appendEntry(it->_value->getName() + " (Game)", idx); + _kmPopUp->appendEntry(it->_value->getName() + _(" (Game)"), idx); _keymapTable[idx++] = it->_value; } } @@ -168,7 +170,7 @@ void RemapDialog::reflowLayout() { widg.actionText = new GUI::StaticTextWidget(this, 0, 0, 0, 0, "", Graphics::kTextAlignRight); widg.keyButton = - new GUI::ButtonWidget(this, 0, 0, 0, 0, "", kRemapCmd + i); + new GUI::ButtonWidget(this, 0, 0, 0, 0, "", 0, kRemapCmd + i); _keymapWidgets.push_back(widg); } else { widg = _keymapWidgets[i]; diff --git a/backends/midi/alsa.cpp b/backends/midi/alsa.cpp index c38537248c..a82fffdf0d 100644 --- a/backends/midi/alsa.cpp +++ b/backends/midi/alsa.cpp @@ -269,7 +269,7 @@ public: } MusicDevices getDevices() const; - Common::Error createInstance(MidiDriver **mididriver) const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; }; #define perm_ok(pinfo,bits) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits)) @@ -315,21 +315,12 @@ MusicDevices AlsaMusicPlugin::getDevices() const { return devices; } -Common::Error AlsaMusicPlugin::createInstance(MidiDriver **mididriver) const { +Common::Error AlsaMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { *mididriver = new MidiDriver_ALSA(); return Common::kNoError; } -MidiDriver *MidiDriver_ALSA_create() { - MidiDriver *mididriver; - - AlsaMusicPlugin p; - p.createInstance(&mididriver); - - return mididriver; -} - //#if PLUGIN_ENABLED_DYNAMIC(ALSA) //REGISTER_PLUGIN_DYNAMIC(ALSA, PLUGIN_TYPE_MUSIC, AlsaMusicPlugin); //#else diff --git a/backends/midi/camd.cpp b/backends/midi/camd.cpp index e4ca3569f2..3486532549 100644 --- a/backends/midi/camd.cpp +++ b/backends/midi/camd.cpp @@ -177,7 +177,7 @@ public: } MusicDevices getDevices() const; - Common::Error createInstance(MidiDriver **mididriver) const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; }; MusicDevices CamdMusicPlugin::getDevices() const { @@ -188,21 +188,12 @@ MusicDevices CamdMusicPlugin::getDevices() const { return devices; } -Common::Error CamdMusicPlugin::createInstance(MidiDriver **mididriver) const { +Common::Error CamdMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { *mididriver = new MidiDriver_CAMD(); return Common::kNoError; } -MidiDriver *MidiDriver_CAMD_create() { - MidiDriver *mididriver; - - CamdMusicPlugin p; - p.createInstance(&mididriver); - - return mididriver; -} - //#if PLUGIN_ENABLED_DYNAMIC(CAMD) //REGISTER_PLUGIN_DYNAMIC(CAMD, PLUGIN_TYPE_MUSIC, CamdMusicPlugin); //#else diff --git a/backends/midi/coreaudio.cpp b/backends/midi/coreaudio.cpp index d52547c997..aa0ad75f0a 100644 --- a/backends/midi/coreaudio.cpp +++ b/backends/midi/coreaudio.cpp @@ -218,7 +218,7 @@ public: } MusicDevices getDevices() const; - Common::Error createInstance(MidiDriver **mididriver) const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; }; MusicDevices CoreAudioMusicPlugin::getDevices() const { @@ -229,21 +229,12 @@ MusicDevices CoreAudioMusicPlugin::getDevices() const { return devices; } -Common::Error CoreAudioMusicPlugin::createInstance(MidiDriver **mididriver) const { +Common::Error CoreAudioMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { *mididriver = new MidiDriver_CORE(); return Common::kNoError; } -MidiDriver *MidiDriver_CORE_create() { - MidiDriver *mididriver; - - CoreAudioMusicPlugin p; - p.createInstance(&mididriver); - - return mididriver; -} - //#if PLUGIN_ENABLED_DYNAMIC(COREAUDIO) //REGISTER_PLUGIN_DYNAMIC(COREAUDIO, PLUGIN_TYPE_MUSIC, CoreAudioMusicPlugin); //#else diff --git a/backends/midi/coremidi.cpp b/backends/midi/coremidi.cpp index e48b98a807..08f36a8b0f 100644 --- a/backends/midi/coremidi.cpp +++ b/backends/midi/coremidi.cpp @@ -190,7 +190,7 @@ public: } MusicDevices getDevices() const; - Common::Error createInstance(MidiDriver **mididriver) const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; }; MusicDevices CoreMIDIMusicPlugin::getDevices() const { @@ -201,21 +201,12 @@ MusicDevices CoreMIDIMusicPlugin::getDevices() const { return devices; } -Common::Error CoreMIDIMusicPlugin::createInstance(MidiDriver **mididriver) const { +Common::Error CoreMIDIMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { *mididriver = new MidiDriver_CoreMIDI(); return Common::kNoError; } -MidiDriver *MidiDriver_CoreMIDI_create() { - MidiDriver *mididriver; - - CoreMIDIMusicPlugin p; - p.createInstance(&mididriver); - - return mididriver; -} - //#if PLUGIN_ENABLED_DYNAMIC(COREMIDI) //REGISTER_PLUGIN_DYNAMIC(COREMIDI, PLUGIN_TYPE_MUSIC, CoreMIDIMusicPlugin); //#else diff --git a/backends/midi/dmedia.cpp b/backends/midi/dmedia.cpp index 1ec79d8513..8c006b2cd9 100644 --- a/backends/midi/dmedia.cpp +++ b/backends/midi/dmedia.cpp @@ -199,7 +199,7 @@ public: } MusicDevices getDevices() const; - Common::Error createInstance(MidiDriver **mididriver) const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; }; MusicDevices DMediaMusicPlugin::getDevices() const { @@ -224,21 +224,12 @@ MusicDevices DMediaMusicPlugin::getDevices() const { return devices; } -Common::Error DMediaMusicPlugin::createInstance(MidiDriver **mididriver) const { +Common::Error DMediaMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { *mididriver = new MidiDriver_DMEDIA(); return Common::kNoError; } -MidiDriver *MidiDriver_DMEDIA_create() { - MidiDriver *mididriver; - - DMediaMusicPlugin p; - p.createInstance(&mididriver); - - return mididriver; -} - //#if PLUGIN_ENABLED_DYNAMIC(DMEDIA) //REGISTER_PLUGIN_DYNAMIC(DMEDIA, PLUGIN_TYPE_MUSIC, DMediaMusicPlugin); //#else diff --git a/backends/midi/seq.cpp b/backends/midi/seq.cpp index 55c8239562..b1815adee5 100644 --- a/backends/midi/seq.cpp +++ b/backends/midi/seq.cpp @@ -28,7 +28,7 @@ * both the QuickTime support and (vkeybd http://www.alsa-project.org/~iwai/alsa.html) */ -#if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__) && !defined(__MINT__) +#if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__) && !defined(__MINT__) && !defined(__ANDROID__) #include "common/util.h" #include "sound/musicplugin.h" @@ -184,7 +184,7 @@ public: } MusicDevices getDevices() const; - Common::Error createInstance(MidiDriver **mididriver) const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; }; MusicDevices SeqMusicPlugin::getDevices() const { @@ -195,21 +195,12 @@ MusicDevices SeqMusicPlugin::getDevices() const { return devices; } -Common::Error SeqMusicPlugin::createInstance(MidiDriver **mididriver) const { +Common::Error SeqMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { *mididriver = new MidiDriver_SEQ(); return Common::kNoError; } -MidiDriver *MidiDriver_SEQ_create() { - MidiDriver *mididriver; - - SeqMusicPlugin p; - p.createInstance(&mididriver); - - return mididriver; -} - //#if PLUGIN_ENABLED_DYNAMIC(SEQ) //REGISTER_PLUGIN_DYNAMIC(SEQ, PLUGIN_TYPE_MUSIC, SeqMusicPlugin); //#else diff --git a/backends/midi/stmidi.cpp b/backends/midi/stmidi.cpp index f99f8f74dd..b00188dfea 100644 --- a/backends/midi/stmidi.cpp +++ b/backends/midi/stmidi.cpp @@ -127,8 +127,7 @@ public: } MusicDevices getDevices() const; - Common::Error createInstance(MidiDriver **mididriver) - const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; }; MusicDevices StMidiMusicPlugin::getDevices() const { @@ -139,21 +138,12 @@ MusicDevices StMidiMusicPlugin::getDevices() const { return devices; } -Common::Error StMidiMusicPlugin::createInstance(MidiDriver **mididriver) const { +Common::Error StMidiMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { *mididriver = new MidiDriver_STMIDI(); return Common::kNoError; } -MidiDriver *MidiDriver_STMIDI_create() { - MidiDriver *mididriver; - - StMidiMusicPlugin p; - p.createInstance(&mididriver); - - return mididriver; -} - //#if PLUGIN_ENABLED_DYNAMIC(STMIDI) //REGISTER_PLUGIN_DYNAMIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin); //#else diff --git a/backends/midi/timidity.cpp b/backends/midi/timidity.cpp index 1a44e62b16..f507f1e00a 100644 --- a/backends/midi/timidity.cpp +++ b/backends/midi/timidity.cpp @@ -530,7 +530,7 @@ public: } MusicDevices getDevices() const; - Common::Error createInstance(MidiDriver **mididriver) const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; }; MusicDevices TimidityMusicPlugin::getDevices() const { @@ -539,21 +539,12 @@ MusicDevices TimidityMusicPlugin::getDevices() const { return devices; } -Common::Error TimidityMusicPlugin::createInstance(MidiDriver **mididriver) const { +Common::Error TimidityMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { *mididriver = new MidiDriver_TIMIDITY(); return Common::kNoError; } -MidiDriver *MidiDriver_TIMIDITY_create() { - MidiDriver *mididriver; - - TimidityMusicPlugin p; - p.createInstance(&mididriver); - - return mididriver; -} - //#if PLUGIN_ENABLED_DYNAMIC(TIMIDITY) //REGISTER_PLUGIN_DYNAMIC(TIMIDITY, PLUGIN_TYPE_MUSIC, TimidityMusicPlugin); //#else diff --git a/backends/midi/windows.cpp b/backends/midi/windows.cpp index 036029644e..da44c40978 100644 --- a/backends/midi/windows.cpp +++ b/backends/midi/windows.cpp @@ -24,12 +24,15 @@ #if defined(WIN32) && !defined(_WIN32_WCE) +#define WIN32_LEAN_AND_MEAN #include <windows.h> // winnt.h defines ARRAYSIZE, but we want our own one... #undef ARRAYSIZE #include "sound/musicplugin.h" #include "sound/mpu401.h" +#include "common/config-manager.h" +#include "common/translation.h" #include <mmsystem.h> @@ -46,11 +49,12 @@ private: HANDLE _streamEvent; HMIDIOUT _mo; bool _isOpen; + int _device; void check_error(MMRESULT result); public: - MidiDriver_WIN() : _isOpen(false) { } + MidiDriver_WIN(int deviceIndex) : _isOpen(false), _device(deviceIndex) { } int open(); void close(); void send(uint32 b); @@ -62,7 +66,7 @@ int MidiDriver_WIN::open() { return MERR_ALREADY_OPEN; _streamEvent = CreateEvent(NULL, true, true, NULL); - MMRESULT res = midiOutOpen((HMIDIOUT *)&_mo, MIDI_MAPPER, (DWORD_PTR)_streamEvent, 0, CALLBACK_EVENT); + MMRESULT res = midiOutOpen((HMIDIOUT *)&_mo, _device, (DWORD_PTR)_streamEvent, 0, CALLBACK_EVENT); if (res != MMSYSERR_NOERROR) { check_error(res); CloseHandle(_streamEvent); @@ -150,7 +154,7 @@ void MidiDriver_WIN::check_error(MMRESULT result) { class WindowsMusicPlugin : public MusicPluginObject { public: const char *getName() const { - return "Windows MIDI"; + return _s("Windows MIDI"); } const char *getId() const { @@ -158,32 +162,43 @@ public: } MusicDevices getDevices() const; - Common::Error createInstance(MidiDriver **mididriver) const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; }; MusicDevices WindowsMusicPlugin::getDevices() const { MusicDevices devices; - // TODO: Return a different music type depending on the configuration - // TODO: List the available devices - devices.push_back(MusicDevice(this, "", MT_GM)); + int numDevs = midiOutGetNumDevs(); + MIDIOUTCAPS tmp; + + for (int i = 0; i < numDevs; i++) { + if (midiOutGetDevCaps(i, &tmp, sizeof(MIDIOUTCAPS)) != MMSYSERR_NOERROR) + break; + // There is no way to detect the "MusicType" so I just set it to MT_GM + // The user will have to manually select his MT32 type device and his GM type device. + devices.push_back(MusicDevice(this, tmp.szPname, MT_GM)); + } return devices; } -Common::Error WindowsMusicPlugin::createInstance(MidiDriver **mididriver) const { - *mididriver = new MidiDriver_WIN(); +Common::Error WindowsMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle dev) const { + int devIndex = 0; + bool found = false; + + if (dev) { + MusicDevices i = getDevices(); + for (MusicDevices::iterator d = i.begin(); d != i.end(); d++) { + if (d->getCompleteId().equals(MidiDriver::getDeviceString(dev, MidiDriver::kDeviceId))) { + found = true; + break; + } + devIndex++; + } + } + *mididriver = new MidiDriver_WIN(found ? devIndex : 0); return Common::kNoError; } -MidiDriver *MidiDriver_WIN_create() { - MidiDriver *mididriver; - - WindowsMusicPlugin p; - p.createInstance(&mididriver); - - return mididriver; -} - //#if PLUGIN_ENABLED_DYNAMIC(WINDOWS) //REGISTER_PLUGIN_DYNAMIC(WINDOWS, PLUGIN_TYPE_MUSIC, WindowsMusicPlugin); //#else diff --git a/backends/midi/ypa1.cpp b/backends/midi/ypa1.cpp index fe65d02c10..fb114d625c 100644 --- a/backends/midi/ypa1.cpp +++ b/backends/midi/ypa1.cpp @@ -117,7 +117,7 @@ public: } MusicDevices getDevices() const; - Common::Error createInstance(MidiDriver **mididriver) const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; }; MusicDevices YamahaPa1MusicPlugin::getDevices() const { @@ -128,21 +128,12 @@ MusicDevices YamahaPa1MusicPlugin::getDevices() const { return devices; } -Common::Error YamahaPa1MusicPlugin::createInstance(MidiDriver **mididriver) const { +Common::Error YamahaPa1MusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { *mididriver = new MidiDriver_YamahaPa1(); return Common::kNoError; } -MidiDriver *MidiDriver_YamahaPa1_create() { - MidiDriver *mididriver; - - YamahaPa1MusicPlugin p; - p.createInstance(&mididriver); - - return mididriver; -} - //#if PLUGIN_ENABLED_DYNAMIC(YPA1) //REGISTER_PLUGIN_DYNAMIC(YPA1, PLUGIN_TYPE_MUSIC, YamahaPa1MusicPlugin); //#else diff --git a/backends/midi/zodiac.cpp b/backends/midi/zodiac.cpp index b9cb46912a..e848315ca4 100644 --- a/backends/midi/zodiac.cpp +++ b/backends/midi/zodiac.cpp @@ -135,7 +135,7 @@ public: } MusicDevices getDevices() const; - Common::Error createInstance(MidiDriver **mididriver) const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; }; MusicDevices ZodiacMusicPlugin::getDevices() const { @@ -146,21 +146,12 @@ MusicDevices ZodiacMusicPlugin::getDevices() const { return devices; } -Common::Error ZodiacMusicPlugin::createInstance(MidiDriver **mididriver) const { +Common::Error ZodiacMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { *mididriver = new MidiDriver_Zodiac(); return Common::kNoError; } -MidiDriver *MidiDriver_Zodiac_create() { - MidiDriver *mididriver; - - ZodiacMusicPlugin p; - p.createInstance(&mididriver); - - return mididriver; -} - //#if PLUGIN_ENABLED_DYNAMIC(ZODIAC) //REGISTER_PLUGIN_DYNAMIC(ZODIAC, PLUGIN_TYPE_MUSIC, ZodiacMusicPlugin); //#else diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp index 3a18014b3a..e7d0764c11 100644 --- a/backends/modular-backend.cpp +++ b/backends/modular-backend.cpp @@ -92,13 +92,15 @@ int ModularBackend::getGraphicsMode() const { } #ifdef USE_RGB_COLOR + Graphics::PixelFormat ModularBackend::getScreenFormat() const { return _graphicsManager->getScreenFormat(); } -Common::List<Graphics::PixelFormat> ModularBackend::getSupportedFormats() { +Common::List<Graphics::PixelFormat> ModularBackend::getSupportedFormats() const { return _graphicsManager->getSupportedFormats(); } + #endif void ModularBackend::initSize(uint w, uint h, const Graphics::PixelFormat *format ) { diff --git a/backends/modular-backend.h b/backends/modular-backend.h index a60fccc876..63e13059cb 100644 --- a/backends/modular-backend.h +++ b/backends/modular-backend.h @@ -76,7 +76,7 @@ public: virtual int getGraphicsMode() const; #ifdef USE_RGB_COLOR virtual Graphics::PixelFormat getScreenFormat() const; - virtual Common::List<Graphics::PixelFormat> getSupportedFormats(); + virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const; #endif virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL); virtual int getScreenChangeID() const; diff --git a/backends/module.mk b/backends/module.mk index 146253248b..801c98135f 100644 --- a/backends/module.mk +++ b/backends/module.mk @@ -29,6 +29,7 @@ MODULE_OBJS := \ graphics/gp2xwizsdl/gp2xwizsdl-graphics.o \ graphics/linuxmotosdl/linuxmotosdl-graphics.o \ graphics/opengl/glerrorcheck.o \ + graphics/opengl/gltexture.o \ graphics/opengl/opengl-graphics.o \ graphics/openglsdl/openglsdl-graphics.o \ graphics/sdl/sdl-graphics.o \ diff --git a/backends/platform/PalmOS/Src/launcher/forms/formSkins.cpp b/backends/platform/PalmOS/Src/launcher/forms/formSkins.cpp index b4c1e222d0..9566a25311 100644 --- a/backends/platform/PalmOS/Src/launcher/forms/formSkins.cpp +++ b/backends/platform/PalmOS/Src/launcher/forms/formSkins.cpp @@ -107,7 +107,7 @@ static void SkinsFormExit(Boolean bSave) { listP = (ListType *)GetObjectPtr(SkinsSkinList); selected = LstGetSelection(listP); - if (bSave && selected == -1) { // may never occured... + if (bSave && selected == -1) { // may never occurred... FrmCustomAlert(FrmWarnAlert, "You didn't select a skin.", 0, 0); return; } @@ -164,7 +164,7 @@ static void SkinsFormBeam() { listP = (ListType *)GetObjectPtr(SkinsSkinList); selected = LstGetSelection(listP); - if (selected == -1) { // may never occured... + if (selected == -1) { // may never occurred... FrmCustomAlert(FrmWarnAlert, "You didn't select a skin.", 0, 0); return; } @@ -187,7 +187,7 @@ static void SkinsFormDelete() { listP = (ListType *)GetObjectPtr(SkinsSkinList); selected = LstGetSelection(listP); - if (selected == -1) { // may never occured... + if (selected == -1) { // may never occurred... FrmCustomAlert(FrmInfoAlert, "You didn't select a skin.", 0, 0); return; } diff --git a/backends/platform/PalmOS/Src/launcher/forms/formmusic.cpp b/backends/platform/PalmOS/Src/launcher/forms/formmusic.cpp index 58eaa5b5fc..48399efa95 100644 --- a/backends/platform/PalmOS/Src/launcher/forms/formmusic.cpp +++ b/backends/platform/PalmOS/Src/launcher/forms/formmusic.cpp @@ -258,7 +258,7 @@ static void MusicFormInit(UInt16 index) { ogameInfoP = (GameInfoType *)MemHandleLock(recordH); if (!ogameInfoP) { - FrmCustomAlert(FrmErrorAlert, "An error occured.",0,0); + FrmCustomAlert(FrmErrorAlert, "An error occurred.",0,0); return; } diff --git a/backends/platform/PalmOS/Src/launcher/launch.cpp b/backends/platform/PalmOS/Src/launcher/launch.cpp index cb2d52b20e..d83a34e94c 100644 --- a/backends/platform/PalmOS/Src/launcher/launch.cpp +++ b/backends/platform/PalmOS/Src/launcher/launch.cpp @@ -468,7 +468,7 @@ Boolean StartScummVM(Int16 engine) { return false; } - // reset mode if screen rotation occured (DIA only) + // reset mode if screen rotation occurred (DIA only) if (!direct && OPTIONS_TST(kOptCollapsible)) { UInt8 mode = PalmScreenSize(0,0, &(gVars->screenFullWidth), &(gVars->screenFullHeight)); OPTIONS_RST(kOptModeLandscape); diff --git a/backends/platform/android/README.build b/backends/platform/android/README.build index fa56bfc180..3d1cf433a7 100644 --- a/backends/platform/android/README.build +++ b/backends/platform/android/README.build @@ -2,41 +2,38 @@ 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 +1. Android SDK +2. An arm-oe-linux-androideabi 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 +(*) Any other sane Android toolchain should be easy to use, but this +is the toolchain prefix that is used by default. You can trivially +find and modify the single location where it appears in ./configure if +you have some other prefix variation. -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 +In detail: -2. Android SDK +1. Android SDK -Download and install somewhere. +Download the SDK from http://developer.android.com/ and install +somewhere. You will need both the API level 8 (aka Android 2.2) and +API level 3 (aka Android 1.5) platforms. -3. arm-android-eabi GCC toolchain +2. arm-*-linux-androideabi GCC toolchain You have several choices for toolchains: -- Use Google arm-eabi prebuilt toolchain. + - 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 +of shell wrapper scripts that convert "arm-oe-linux-androideabi-foo" to "arm-eabi-foo -mandroid". For example, I use this script: @@ -44,17 +41,24 @@ For example, I use this script: 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. +arm-oe-android-linuxeabi-gcc, arm-oe-android-linuxeabi-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-oe-android-linuxeabi-strip +symlink to the tool directly. -- Build your own arm-android-eabi toolchain from GCC source. +In practice you will probably need significant linker command line +massaging in order to get the crtbegin/end and libraries all linked in +the right way. It's not hard to do manually, but it is annoying to +script in a general purpose way. -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 + - Build your own arm-*-linux-androideabi toolchain from GCC source. + +This is lots of fun, but will become significantly easier once gcc-4.6 +is released. In the interim, I suggest using my precompiled Android +openembedded-based toolchain: + wget http://commondatastorage.googleapis.com/anr/sdk/android-2.2-i686-linux-armv5te-linux-androideabi-toolchain-android.tar.bz2 + sudo tar jxf android-2.2-i686-linux-armv5te-linux-androideabi-toolchain-android.tar.bz2 -C / + . /usr/local/android/arm/environment-setup Alternatively, do a websearch - there are several other cross-compile toolchains around. @@ -63,18 +67,25 @@ toolchains around. Building ScummVM ================ +Apply the theme engine patch: + + patch -p1 < backends/platform/android/scummvm-android-themeengine.patch + +(Optionally) compress scummmodern.zip: +(ScummVM usually ships it uncompressed, but Android can read it more +efficiently if it is compressed *before* adding it to the apk) + + ( cd gui/themes/scummmodern && zip -f ../scummmodern.zip ) + +Then build 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 + # You also want to ensure your arm-oe-linux-androideabi toolchain is in $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 diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp index a6258df554..f6af0fcff5 100644 --- a/backends/platform/android/android.cpp +++ b/backends/platform/android/android.cpp @@ -31,10 +31,6 @@ #if defined(ANDROID_BACKEND) -#define ANDROID_VERSION_GE(major,minor) \ - (ANDROID_MAJOR_VERSION > (major) || \ - (ANDROID_MAJOR_VERSION == (major) && ANDROID_MINOR_VERSION >= (minor))) - #include <jni.h> #include <string.h> @@ -45,7 +41,6 @@ #include <GLES/gl.h> #include <GLES/glext.h> -#include <EGL/egl.h> #include <android/log.h> #include "common/archive.h" @@ -78,6 +73,14 @@ #undef JNIEXPORT #define JNIEXPORT __attribute__ ((visibility("default"))) +// This replaces the bionic libc assert message with something that +// actually prints the assertion failure before aborting. +extern "C" +void __assert(const char *file, int line, const char *expr) { + __android_log_assert(expr, LOG_TAG, "%s:%d: Assertion failure: %s", + file, line, expr); +} + static JavaVM *cached_jvm; static jfieldID FID_Event_type; static jfieldID FID_Event_synthetic; @@ -162,20 +165,19 @@ private: jmethodID MID_getPluginDirectories; jmethodID MID_setupScummVMSurface; jmethodID MID_destroyScummVMSurface; + jmethodID MID_swapBuffers; int _screen_changeid; - EGLDisplay _egl_display; - EGLSurface _egl_surface; - EGLint _egl_surface_width; - EGLint _egl_surface_height; + int _egl_surface_width; + int _egl_surface_height; bool _force_redraw; // Game layer GLESPaletteTexture* _game_texture; int _shake_offset; + Common::Rect _focus_rect; bool _full_screen_dirty; - Common::Array<Common::Rect> _dirty_rects; // Overlay layer GLES4444Texture* _overlay_texture; @@ -195,6 +197,7 @@ private: pthread_t _timer_thread; static void* timerThreadFunc(void* arg); + bool _enable_zoning; bool _virtkeybd_on; Common::SaveFileManager *_savefile; @@ -217,6 +220,11 @@ public: static OSystem_Android* fromJavaObject(JNIEnv* env, jobject obj); virtual void initBackend(); void addPluginDirectories(Common::FSList &dirs) const; + void enableZoning(bool enable) { _enable_zoning = enable; } + void setSurfaceSize(int width, int height) { + _egl_surface_width = width; + _egl_surface_height = height; + } virtual bool hasFeature(Feature f); virtual void setFeatureState(Feature f, bool enable); @@ -297,8 +305,6 @@ public: OSystem_Android::OSystem_Android(jobject am) : _back_ptr(0), - _egl_display(EGL_NO_DISPLAY), - _egl_surface(EGL_NO_SURFACE), _screen_changeid(0), _force_redraw(false), _game_texture(NULL), @@ -307,6 +313,7 @@ OSystem_Android::OSystem_Android(jobject am) _use_mouse_palette(false), _show_mouse(false), _show_overlay(false), + _enable_zoning(false), _savefile(0), _mixer(0), _timer(0), @@ -362,6 +369,7 @@ bool OSystem_Android::initJavaHooks(JNIEnv* env, jobject self) { FIND_METHOD(getPluginDirectories, "()[Ljava/lang/String;"); FIND_METHOD(setupScummVMSurface, "()V"); FIND_METHOD(destroyScummVMSurface, "()V"); + FIND_METHOD(swapBuffers, "()Z"); #undef FIND_METHOD @@ -574,6 +582,7 @@ int OSystem_Android::getGraphicsMode() const { } void OSystem_Android::setupScummVMSurface() { + ENTER("setupScummVMSurface"); JNIEnv* env = JNU_GetEnv(); env->CallVoidMethod(_back_ptr, MID_setupScummVMSurface); if (env->ExceptionCheck()) @@ -581,37 +590,8 @@ void OSystem_Android::setupScummVMSurface() { // EGL set up with a new surface. Initialise OpenGLES context. - _egl_display = eglGetCurrentDisplay(); - _egl_surface = eglGetCurrentSurface(EGL_DRAW); - - static bool log_version = true; - if (log_version) { - __android_log_print(ANDROID_LOG_INFO, LOG_TAG, - "Using EGL %s (%s); GL %s/%s (%s)", - eglQueryString(_egl_display, EGL_VERSION), - eglQueryString(_egl_display, EGL_VENDOR), - glGetString(GL_VERSION), - glGetString(GL_RENDERER), - glGetString(GL_VENDOR)); - log_version = false; // only log this once - } - GLESTexture::initGLExtensions(); - if (!eglQuerySurface(_egl_display, _egl_surface, - EGL_WIDTH, &_egl_surface_width) || - !eglQuerySurface(_egl_display, _egl_surface, - EGL_HEIGHT, &_egl_surface_height)) { - JNU_ThrowByName(env, "java/lang/RuntimeException", - "Error fetching EGL surface width/height"); - return; - } - __android_log_print(ANDROID_LOG_INFO, LOG_TAG, - "New surface is %dx%d", - _egl_surface_width, _egl_surface_height); - - CHECK_GL_ERROR(); - // Turn off anything that looks like 3D ;) glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); @@ -645,20 +625,18 @@ void OSystem_Android::setupScummVMSurface() { _mouse_texture->reinitGL(); glViewport(0, 0, _egl_surface_width, _egl_surface_height); + glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrthof(0, _egl_surface_width, _egl_surface_height, 0, -1, 1); - glMatrixMode(GL_MODELVIEW); glLoadIdentity(); + clearFocusRectangle(); CHECK_GL_ERROR(); - - _force_redraw = true; } void OSystem_Android::destroyScummVMSurface() { - _egl_surface = EGL_NO_SURFACE; JNIEnv* env = JNU_GetEnv(); env->CallVoidMethod(_back_ptr, MID_destroyScummVMSurface); // Can't use OpenGLES functions after this @@ -676,7 +654,7 @@ void OSystem_Android::initSize(uint width, uint height, _overlay_texture->allocBuffer(overlay_width, overlay_height); // Don't know mouse size yet - it gets reallocated in - // setMouseCursor. We need the palette allocated before + // setMouseCursor. We need the palette allocated before // setMouseCursor however, so just take a guess at the desired // size (it's small). _mouse_texture->allocBuffer(20, 20); @@ -691,7 +669,7 @@ int16 OSystem_Android::getWidth() { } void OSystem_Android::setPalette(const byte* colors, uint start, uint num) { - ENTER("setPalette(%p, %u, %u)", colors, start, num); + ENTER("setPalette(%p, %u, %u)", colors, start, num); if (!_use_mouse_palette) _setCursorPalette(colors, start, num); @@ -739,8 +717,11 @@ void OSystem_Android::updateScreen() { glPushMatrix(); - if (_shake_offset != 0) { - // This is the only case where _game_texture doesn't + if (_shake_offset != 0 || + (!_focus_rect.isEmpty() && + !Common::Rect(_game_texture->width(), + _game_texture->height()).contains(_focus_rect))) { + // These are the only cases where _game_texture doesn't // cover the entire screen. glClearColorx(0, 0, 0, 1 << 16); glClear(GL_COLOR_BUFFER_BIT); @@ -749,15 +730,29 @@ void OSystem_Android::updateScreen() { glTranslatex(0, -_shake_offset << 16, 0); } - _game_texture->drawTexture(0, 0, - _egl_surface_width, _egl_surface_height); + if (_focus_rect.isEmpty()) { + _game_texture->drawTexture(0, 0, + _egl_surface_width, _egl_surface_height); + } else { + glPushMatrix(); + glScalex(xdiv(_egl_surface_width, _focus_rect.width()), + xdiv(_egl_surface_height, _focus_rect.height()), + 1 << 16); + glTranslatex(-_focus_rect.left << 16, -_focus_rect.top << 16, 0); + glScalex(xdiv(_game_texture->width(), _egl_surface_width), + xdiv(_game_texture->height(), _egl_surface_height), + 1 << 16); + _game_texture->drawTexture(0, 0, + _egl_surface_width, _egl_surface_height); + glPopMatrix(); + } CHECK_GL_ERROR(); if (_show_overlay) { _overlay_texture->drawTexture(0, 0, - _egl_surface_width, - _egl_surface_height); + _egl_surface_width, + _egl_surface_height); CHECK_GL_ERROR(); } @@ -765,8 +760,8 @@ void OSystem_Android::updateScreen() { glPushMatrix(); glTranslatex(-_mouse_hotspot.x << 16, - -_mouse_hotspot.y << 16, - 0); + -_mouse_hotspot.y << 16, + 0); // Scale up ScummVM -> OpenGL (pixel) coordinates int texwidth, texheight; @@ -778,8 +773,8 @@ void OSystem_Android::updateScreen() { texheight = getHeight(); } glScalex(xdiv(_egl_surface_width, texwidth), - xdiv(_egl_surface_height, texheight), - 1 << 16); + xdiv(_egl_surface_height, texheight), + 1 << 16); // Note the extra half texel to position the mouse in // the middle of the x,y square: @@ -801,14 +796,11 @@ void OSystem_Android::updateScreen() { CHECK_GL_ERROR(); - if (!eglSwapBuffers(_egl_display, _egl_surface)) { - EGLint error = eglGetError(); - warning("eglSwapBuffers exited with error 0x%x", error); - // Some errors mean we need to reinit GL - if (error == EGL_CONTEXT_LOST) { - destroyScummVMSurface(); - setupScummVMSurface(); - } + JNIEnv* env = JNU_GetEnv(); + if (!env->CallBooleanMethod(_back_ptr, MID_swapBuffers)) { + // Context lost -> need to reinit GL + destroyScummVMSurface(); + setupScummVMSurface(); } } @@ -841,26 +833,18 @@ void OSystem_Android::fillScreen(uint32 col) { void OSystem_Android::setFocusRectangle(const Common::Rect& rect) { ENTER("setFocusRectangle(%d,%d,%d,%d)", rect.left, rect.top, rect.right, rect.bottom); -#if 0 - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrthof(rect.left, rect.right, rect.top, rect.bottom, 0, 1); - glMatrixMode(GL_MODELVIEW); - - _force_redraw = true; -#endif + if (_enable_zoning) { + _focus_rect = rect; + _force_redraw = true; + } } void OSystem_Android::clearFocusRectangle() { ENTER("clearFocusRectangle()"); -#if 0 - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrthof(0, _egl_surface_width, _egl_surface_height, 0, -1, 1); - glMatrixMode(GL_MODELVIEW); - - _force_redraw = true; -#endif + if (_enable_zoning) { + _focus_rect = Common::Rect(); + _force_redraw = true; + } } void OSystem_Android::showOverlay() { @@ -1338,6 +1322,17 @@ void AndroidPluginProvider::addCustomDirectories(Common::FSList &dirs) const { } #endif +static void ScummVM_enableZoning(JNIEnv* env, jobject self, jboolean enable) { + OSystem_Android* cpp_obj = OSystem_Android::fromJavaObject(env, self); + cpp_obj->enableZoning(enable); +} + +static void ScummVM_setSurfaceSize(JNIEnv* env, jobject self, + jint width, jint height) { + OSystem_Android* cpp_obj = OSystem_Android::fromJavaObject(env, self); + cpp_obj->setSurfaceSize(width, height); +} + const static JNINativeMethod gMethods[] = { { "create", "(Landroid/content/res/AssetManager;)V", (void*)ScummVM_create }, @@ -1352,6 +1347,10 @@ const static JNINativeMethod gMethods[] = { (void*)ScummVM_setConfManInt }, { "setConfMan", "(Ljava/lang/String;Ljava/lang/String;)V", (void*)ScummVM_setConfManString }, + { "enableZoning", "(Z)V", + (void*)ScummVM_enableZoning }, + { "setSurfaceSize", "(II)V", + (void*)ScummVM_setSurfaceSize }, }; JNIEXPORT jint JNICALL diff --git a/backends/platform/android/android.mk b/backends/platform/android/android.mk index 0bc8fa265e..95e848e0d9 100644 --- a/backends/platform/android/android.mk +++ b/backends/platform/android/android.mk @@ -4,7 +4,6 @@ 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 @@ -12,6 +11,14 @@ JAVACFLAGS = -source 1.5 -target 1.5 #LDFLAGS += -Wl,--gc-sections #CXXFLAGS += -ffunction-sections -fdata-sections -fvisibility=hidden -fvisibility-inlines-hidden +resources.ap_: $(srcdir)/dists/android/AndroidManifest.xml $(RESOURCES) $(ASSETS) $(ANDROID_JAR8) $(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_JAR8) -F $@ + +build.tmp/%/resources.ap_: build.tmp/%/AndroidManifest.xml build.stage/%/res/values/strings.xml build.stage/%/res/drawable/scummvm.png $(ANDROID_JAR8) + $(AAPT) package -f -M $< -S build.stage/$*/res -I $(ANDROID_JAR8) -F $@ + 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 diff --git a/backends/platform/android/module.mk b/backends/platform/android/module.mk index fdb0ed2ac4..c7b98b996d 100644 --- a/backends/platform/android/module.mk +++ b/backends/platform/android/module.mk @@ -39,14 +39,22 @@ PLUGIN_RESOURCES = \ #ANDROID_VERSIONCODE = 6 Specified in dists/android/AndroidManifest.xml.in ANDROID_PLUGIN_VERSIONCODE = 6 +# This is a bit silly. I want to compile against the 1.6 android.jar, +# to make the compiler check that I don't use something that requires +# a newer Android. However, in order to use android:installLocation, +# we need to give aapt a version >=8 android.jar - even though the +# result will work ok on 1.5+. +ANDROID_JAR = $(ANDROID_SDK)/platforms/android-1.5/android.jar +ANDROID_JAR8 = $(ANDROID_SDK)/platforms/android-8/android.jar + # 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) + $(QUIET_LINK)$(CXX) -shared $(LDFLAGS) -Wl,-Bsymbolic -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) +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_JAR8) + $(AAPT) package -m -J backends/platform/android -M $< -S $(srcdir)/dists/android/res -I $(ANDROID_JAR8) build.tmp/classes/%.class: $(srcdir)/backends/platform/android/%.java $(srcdir)/backends/platform/android/org/inodes/gus/scummvm/R.java @$(MKDIR) -p $(@D) @@ -63,14 +71,6 @@ build.tmp/plugins/classes.dex: $(JAVA_PLUGIN_SRC:backends/platform/android/%.jav @$(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) \ diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java index f4dca0e7e5..d39aa363ef 100644 --- a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java +++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java @@ -12,7 +12,10 @@ import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; +import javax.microedition.khronos.opengles.GL; +import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.egl.EGL10; +import javax.microedition.khronos.egl.EGL11; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGLContext; import javax.microedition.khronos.egl.EGLDisplay; @@ -30,11 +33,11 @@ import java.util.concurrent.Semaphore; 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 + 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; + boolean scummVMRunning = false; private native void create(AssetManager am); @@ -54,49 +57,49 @@ public class ScummVM implements SurfaceHolder.Callback { 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[] = { + // 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) { + }; + 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, + 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) { + public void surfaceDestroyed(SurfaceHolder holder) { pushEvent(new Event(Event.EVENT_SCREEN_CHANGED)); try { surfaceLock.acquire(); @@ -104,10 +107,10 @@ public class ScummVM implements SurfaceHolder.Callback { Log.e(this.toString(), "Interrupted while waiting for surface lock", e); } - } + } - // Called by ScummVM thread (from initBackend) - private void createScummVMGLContext() { + // 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]; @@ -126,10 +129,11 @@ public class ScummVM implements SurfaceHolder.Callback { eglContext = egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, null); - } + } - // Called by ScummVM thread - protected void setupScummVMSurface() { + // Called by ScummVM thread + static private boolean _log_version = true; + protected void setupScummVMSurface() { try { surfaceLock.acquire(); } catch (InterruptedException e) { @@ -140,10 +144,30 @@ public class ScummVM implements SurfaceHolder.Callback { eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig, nativeSurface, null); egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext); - } - // Called by ScummVM thread - protected void destroyScummVMSurface() { + GL10 gl = (GL10)eglContext.getGL(); + + if (_log_version) { + Log.i(LOG_TAG, String.format("Using EGL %s (%s); GL %s/%s (%s)", + egl.eglQueryString(eglDisplay, EGL10.EGL_VERSION), + egl.eglQueryString(eglDisplay, EGL10.EGL_VENDOR), + gl.glGetString(GL10.GL_VERSION), + gl.glGetString(GL10.GL_RENDERER), + gl.glGetString(GL10.GL_VENDOR))); + _log_version = false; // only log this once + } + + int[] value = new int[1]; + egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_WIDTH, value); + int width = value[0]; + egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_HEIGHT, value); + int height = value[0]; + Log.i(LOG_TAG, String.format("New surface is %dx%d", width, height)); + setSurfaceSize(width, height); + } + + // 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); @@ -152,16 +176,28 @@ public class ScummVM implements SurfaceHolder.Callback { } surfaceLock.release(); - } + } - public void setSurface(SurfaceHolder holder) { + public void setSurface(SurfaceHolder holder) { holder.addCallback(this); - } + } + + final public boolean swapBuffers() { + if (!egl.eglSwapBuffers(eglDisplay, eglSurface)) { + int error = egl.eglGetError(); + Log.w(LOG_TAG, String.format("eglSwapBuffers exited with error 0x%x", error)); + if (error == EGL11.EGL_CONTEXT_LOST) + return false; + } + return true; + } // 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); + final public native void enableZoning(boolean enable); + final public native void setSurfaceSize(int width, int height); // Feed an event to ScummVM. Safe to call from other threads. final public native void pushEvent(Event e); @@ -179,10 +215,10 @@ public class ScummVM implements SurfaceHolder.Callback { protected void showVirtualKeyboard(boolean enable) {} protected String[] getSysArchives() { return new String[0]; } protected String[] getPluginDirectories() { return new String[0]; } - protected void initBackend() throws AudioSetupException { + protected void initBackend() throws AudioSetupException { createScummVMGLContext(); initAudio(); - } + } private static class AudioThread extends Thread { final private int buf_size; @@ -239,7 +275,7 @@ public class ScummVM implements SurfaceHolder.Callback { break; } else if (ret != len) { Log.w(LOG_TAG, String.format( - "Short audio write. Wrote %dB, not %dB", + "Short audio write. Wrote %dB, not %dB", ret, buf.length)); // Buffer is full, so yield cpu for a while Thread.sleep(100); diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java index fb3cd6348f..b37b2b8a52 100644 --- a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java +++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java @@ -1,7 +1,7 @@ package org.inodes.gus.scummvm; -import android.app.AlertDialog; import android.app.Activity; +import android.app.AlertDialog; import android.content.DialogInterface; import android.content.res.Configuration; import android.media.AudioManager; @@ -9,13 +9,14 @@ import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; +import android.util.DisplayMetrics; 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.view.inputmethod.InputMethodManager; import android.widget.Toast; import java.io.IOException; @@ -31,8 +32,27 @@ public class ScummVMActivity extends Activity { private class MyScummVM extends ScummVM { private boolean scummvmRunning = false; + private boolean usingSmallScreen() { + // Multiple screen sizes came in with Android 1.6. Have + // to use reflection in order to continue supporting 1.5 + // devices :( + DisplayMetrics metrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(metrics); + try { + // This 'density' term is very confusing. + int DENSITY_LOW = metrics.getClass().getField("DENSITY_LOW").getInt(null); + int densityDpi = metrics.getClass().getField("densityDpi").getInt(metrics); + return densityDpi <= DENSITY_LOW; + } catch (Exception e) { + return false; + } + } + public MyScummVM() { super(ScummVMActivity.this); + + // Enable ScummVM zoning on 'small' screens. + enableZoning(usingSmallScreen()); } @Override diff --git a/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java b/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java index efa3e1d2ef..7280aac7d4 100644 --- a/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java +++ b/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java @@ -34,6 +34,7 @@ import java.util.zip.ZipFile; import java.util.zip.ZipEntry; public class Unpacker extends Activity { + private final static boolean PLUGINS_ENABLED = true; private final static String META_NEXT_ACTIVITY = "org.inodes.gus.unpacker.nextActivity"; private ProgressBar mProgress; @@ -79,7 +80,6 @@ public class Unpacker extends Activity { 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()); @@ -294,7 +294,7 @@ public class Unpacker extends Activity { Intent intent = new Intent(ScummVMApplication.ACTION_PLUGIN_QUERY); List<ResolveInfo> plugins = getPackageManager() .queryBroadcastReceivers(intent, 0); - if (plugins.isEmpty()) { + if (PLUGINS_ENABLED && plugins.isEmpty()) { // No plugins installed AlertDialog.Builder alert = new AlertDialog.Builder(this) .setTitle(R.string.no_plugins_title) diff --git a/backends/platform/android/video.cpp b/backends/platform/android/video.cpp new file mode 100644 index 0000000000..d4c002fbd0 --- /dev/null +++ b/backends/platform/android/video.cpp @@ -0,0 +1,334 @@ +/* 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/null/null.cpp $ + * $Id: null.cpp 34912 2008-11-06 15:02:50Z fingolfin $ + * + */ + +#include "base/main.h" +#include "graphics/surface.h" + +#include <GLES/gl.h> +#include <GLES/glext.h> + +#include <android/log.h> + +#include "common/rect.h" +#include "common/array.h" +#include "common/util.h" +#include "common/tokenizer.h" + +#include "backends/platform/android/video.h" + +#undef LOG_TAG +#define LOG_TAG "ScummVM-video" + +#if 0 +#define ENTER(args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, args) +#else +#define ENTER(args...) /**/ +#endif + +#if 0 +#define CHECK_GL_ERROR() checkGlError(__FILE__, __LINE__) +static const char* getGlErrStr(GLenum error) { + switch (error) { + case GL_NO_ERROR: return "GL_NO_ERROR"; + case GL_INVALID_ENUM: return "GL_INVALID_ENUM"; + case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION"; + case GL_STACK_OVERFLOW: return "GL_STACK_OVERFLOW"; + case GL_STACK_UNDERFLOW: return "GL_STACK_UNDERFLOW"; + case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY"; + } + + static char buf[40]; + snprintf(buf, sizeof(buf), "(Unknown GL error code 0x%x)", error); + return buf; +} +static void checkGlError(const char* file, int line) { + GLenum error = glGetError(); + if (error != GL_NO_ERROR) + warning("%s:%d: GL error: %s", file, line, getGlErrStr(error)); +} +#else +#define CHECK_GL_ERROR() do {} while (false) +#endif + +// Supported GL extensions +static bool npot_supported = false; +#ifdef GL_OES_draw_texture +static bool draw_tex_supported = false; +#endif + +static inline GLfixed xdiv(int numerator, int denominator) { + assert(numerator < (1<<16)); + return (numerator << 16) / denominator; +} + +template <class T> +static T nextHigher2(T k) { + if (k == 0) + return 1; + --k; + for (uint i = 1; i < sizeof(T)*CHAR_BIT; i <<= 1) + k = k | k >> i; + return k + 1; +} + +void GLESTexture::initGLExtensions() { + const char* ext_string = + reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); + __android_log_print(ANDROID_LOG_INFO, LOG_TAG, + "Extensions: %s", ext_string); + Common::StringTokenizer tokenizer(ext_string, " "); + while (!tokenizer.empty()) { + Common::String token = tokenizer.nextToken(); + if (token == "GL_ARB_texture_non_power_of_two") + npot_supported = true; +#ifdef GL_OES_draw_texture + if (token == "GL_OES_draw_texture") + draw_tex_supported = true; +#endif + } +} + +GLESTexture::GLESTexture() : + _texture_width(0), + _texture_height(0), + _all_dirty(true) +{ + glGenTextures(1, &_texture_name); + // This all gets reset later in allocBuffer: + _surface.w = 0; + _surface.h = 0; + _surface.pitch = _texture_width; + _surface.pixels = NULL; + _surface.bytesPerPixel = 0; +} + +GLESTexture::~GLESTexture() { + debug("Destroying texture %u", _texture_name); + glDeleteTextures(1, &_texture_name); +} + +void GLESTexture::reinitGL() { + glGenTextures(1, &_texture_name); + setDirty(); +} + +void GLESTexture::allocBuffer(GLuint w, GLuint h) { + CHECK_GL_ERROR(); + int bpp = bytesPerPixel(); + _surface.w = w; + _surface.h = h; + _surface.bytesPerPixel = bpp; + + if (w <= _texture_width && h <= _texture_height) + // Already allocated a sufficiently large buffer + return; + + if (npot_supported) { + _texture_width = _surface.w; + _texture_height = _surface.h; + } else { + _texture_width = nextHigher2(_surface.w); + _texture_height = nextHigher2(_surface.h); + } + _surface.pitch = _texture_width * bpp; + + // Allocate room for the texture now, but pixel data gets uploaded + // later (perhaps with multiple TexSubImage2D operations). + CHECK_GL_ERROR(); + glBindTexture(GL_TEXTURE_2D, _texture_name); + CHECK_GL_ERROR(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + CHECK_GL_ERROR(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + CHECK_GL_ERROR(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + CHECK_GL_ERROR(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + CHECK_GL_ERROR(); + glTexImage2D(GL_TEXTURE_2D, 0, glFormat(), + _texture_width, _texture_height, + 0, glFormat(), glType(), NULL); + CHECK_GL_ERROR(); +} + +void GLESTexture::updateBuffer(GLuint x, GLuint y, GLuint w, GLuint h, + const void* buf, int pitch) { + ENTER("updateBuffer(%u, %u, %u, %u, %p, %d)", x, y, w, h, buf, pitch); + glBindTexture(GL_TEXTURE_2D, _texture_name); + + setDirtyRect(Common::Rect(x, y, x+w, y+h)); + + if (static_cast<int>(w) * bytesPerPixel() == pitch) { + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, + glFormat(), glType(), buf); + } else { + // GLES removed the ability to specify pitch, so we + // have to do this row by row. + const byte* src = static_cast<const byte*>(buf); + do { + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, + w, 1, glFormat(), glType(), src); + ++y; + src += pitch; + } while (--h); + } +} + +void GLESTexture::fillBuffer(byte x) { + byte tmpbuf[_surface.h * _surface.w * bytesPerPixel()]; + memset(tmpbuf, 0, _surface.h * _surface.w * bytesPerPixel()); + glBindTexture(GL_TEXTURE_2D, _texture_name); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, _surface.w, _surface.h, + glFormat(), glType(), tmpbuf); + setDirty(); +} + +void GLESTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) { + glBindTexture(GL_TEXTURE_2D, _texture_name); + +#ifdef GL_OES_draw_texture + // Great extension, but only works under specific conditions. + // Still a work-in-progress - disabled for now. + if (false && draw_tex_supported && paletteSize() == 0) { + //glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + const GLint crop[4] = {0, _surface.h, _surface.w, -_surface.h}; + glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, crop); + glDrawTexiOES(x, y, 0, w, h); + } else +#endif + { + const GLfixed tex_width = xdiv(_surface.w, _texture_width); + const GLfixed tex_height = xdiv(_surface.h, _texture_height); + const GLfixed texcoords[] = { + 0, 0, + tex_width, 0, + 0, tex_height, + tex_width, tex_height, + }; + glTexCoordPointer(2, GL_FIXED, 0, texcoords); + + const GLshort vertices[] = { + x, y, + x+w, y, + x, y+h, + x+w, y+h, + }; + glVertexPointer(2, GL_SHORT, 0, vertices); + + assert(ARRAYSIZE(vertices) == ARRAYSIZE(texcoords)); + glDrawArrays(GL_TRIANGLE_STRIP, 0, ARRAYSIZE(vertices)/2); + } + + _all_dirty = false; + _dirty_rect = Common::Rect(); +} + +GLESPaletteTexture::GLESPaletteTexture() : + GLESTexture(), + _texture(NULL) +{ +} + +GLESPaletteTexture::~GLESPaletteTexture() { + delete[] _texture; +} + +void GLESPaletteTexture::allocBuffer(GLuint w, GLuint h) { + CHECK_GL_ERROR(); + int bpp = bytesPerPixel(); + _surface.w = w; + _surface.h = h; + _surface.bytesPerPixel = bpp; + + if (w <= _texture_width && h <= _texture_height) + // Already allocated a sufficiently large buffer + return; + + if (npot_supported) { + _texture_width = _surface.w; + _texture_height = _surface.h; + } else { + _texture_width = nextHigher2(_surface.w); + _texture_height = nextHigher2(_surface.h); + } + _surface.pitch = _texture_width * bpp; + + // Texture gets uploaded later (from drawTexture()) + + byte* new_buffer = new byte[paletteSize() + + _texture_width * _texture_height * bytesPerPixel()]; + if (_texture) { + memcpy(new_buffer, _texture, paletteSize()); // preserve palette + delete[] _texture; + } + _texture = new_buffer; + _surface.pixels = _texture + paletteSize(); +} + +void GLESPaletteTexture::fillBuffer(byte x) { + assert(_surface.pixels); + memset(_surface.pixels, x, _surface.pitch * _surface.h); + setDirty(); +} + +void GLESPaletteTexture::updateBuffer(GLuint x, GLuint y, + GLuint w, GLuint h, + const void* buf, int pitch) { + _all_dirty = true; + + const byte* src = static_cast<const byte*>(buf); + byte* dst = static_cast<byte*>(_surface.getBasePtr(x, y)); + do { + memcpy(dst, src, w * bytesPerPixel()); + dst += _surface.pitch; + src += pitch; + } while (--h); +} + +void GLESPaletteTexture::uploadTexture() const { + const size_t texture_size = + paletteSize() + _texture_width * _texture_height * bytesPerPixel(); + glCompressedTexImage2D(GL_TEXTURE_2D, 0, glType(), + _texture_width, _texture_height, + 0, texture_size, _texture); + CHECK_GL_ERROR(); +} + +void GLESPaletteTexture::drawTexture(GLshort x, GLshort y, GLshort w, GLshort h) { + if (_all_dirty) { + glBindTexture(GL_TEXTURE_2D, _texture_name); + CHECK_GL_ERROR(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + CHECK_GL_ERROR(); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + CHECK_GL_ERROR(); + uploadTexture(); + _all_dirty = false; + } + + GLESTexture::drawTexture(x, y, w, h); +} diff --git a/backends/platform/android/video.h b/backends/platform/android/video.h new file mode 100644 index 0000000000..ee707e4cb5 --- /dev/null +++ b/backends/platform/android/video.h @@ -0,0 +1,140 @@ +/* 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/null/null.cpp $ + * $Id: null.cpp 34912 2008-11-06 15:02:50Z fingolfin $ + * + */ + +#if defined(ANDROID) + +#include <GLES/gl.h> + +#include "graphics/surface.h" + +#include "common/rect.h" +#include "common/array.h" + +class GLESTexture { +public: + static void initGLExtensions(); + + GLESTexture(); + virtual ~GLESTexture(); + virtual void reinitGL(); + virtual void allocBuffer(GLuint width, GLuint height); + const Graphics::Surface* surface_const() const { return &_surface; } + GLuint width() const { return _surface.w; } + GLuint height() const { return _surface.h; } + GLuint texture_name() const { return _texture_name; } + bool dirty() const { return _all_dirty || !_dirty_rect.isEmpty(); } + virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height, + const void* buf, int pitch); + virtual void fillBuffer(byte x); + virtual void drawTexture() { + drawTexture(0, 0, _surface.w, _surface.h); + } + virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h); + +protected: + virtual byte bytesPerPixel() const = 0; + virtual GLenum glFormat() const = 0; + virtual GLenum glType() const = 0; + virtual size_t paletteSize() const { return 0; }; + void setDirty() { + _all_dirty = true; + _dirty_rect = Common::Rect(); + } + void setDirtyRect(const Common::Rect& r) { + if (!_all_dirty) { + if (_dirty_rect.isEmpty()) + _dirty_rect = r; + else + _dirty_rect.extend(r); + } + } + GLuint _texture_name; + Graphics::Surface _surface; + GLuint _texture_width; + GLuint _texture_height; + bool _all_dirty; + Common::Rect _dirty_rect; // Covers dirty area +}; + +// RGBA4444 texture +class GLES4444Texture : public GLESTexture { +protected: + virtual byte bytesPerPixel() const { return 2; } + virtual GLenum glFormat() const { return GL_RGBA; } + virtual GLenum glType() const { return GL_UNSIGNED_SHORT_4_4_4_4; } +}; + +// RGB565 texture +class GLES565Texture : public GLESTexture { +protected: + virtual byte bytesPerPixel() const { return 2; } + virtual GLenum glFormat() const { return GL_RGB; } + virtual GLenum glType() const { return GL_UNSIGNED_SHORT_5_6_5; } +}; + +// RGB888 256-entry paletted texture +class GLESPaletteTexture : public GLESTexture { +public: + GLESPaletteTexture(); + virtual ~GLESPaletteTexture(); + virtual void allocBuffer(GLuint width, GLuint height); + virtual void updateBuffer(GLuint x, GLuint y, GLuint width, GLuint height, + const void* buf, int pitch); + Graphics::Surface* surface() { + setDirty(); + return &_surface; + } + void* pixels() { + setDirty(); + return _surface.pixels; + } + const byte* palette_const() const { return _texture; }; + byte* palette() { + setDirty(); + return _texture; + }; + virtual void drawTexture() { + drawTexture(0, 0, _surface.w, _surface.h); + } + virtual void drawTexture(GLshort x, GLshort y, GLshort w, GLshort h); + virtual void fillBuffer(byte x); +protected: + virtual byte bytesPerPixel() const { return 1; } + virtual GLenum glFormat() const { return GL_RGB; } + virtual GLenum glType() const { return GL_PALETTE8_RGB8_OES; } + virtual size_t paletteSize() const { return 256 * 3; }; + virtual void uploadTexture() const; + byte* _texture; +}; + +// RGBA8888 256-entry paletted texture +class GLESPaletteATexture : public GLESPaletteTexture { +protected: + virtual GLenum glFormat() const { return GL_RGBA; } + virtual GLenum glType() const { return GL_PALETTE8_RGBA8_OES; } + virtual size_t paletteSize() const { return 256 * 4; }; +}; + +#endif diff --git a/backends/platform/dc/dc.h b/backends/platform/dc/dc.h index 8a122ebb27..e87a0a8c90 100644 --- a/backends/platform/dc/dc.h +++ b/backends/platform/dc/dc.h @@ -86,7 +86,7 @@ class OSystem_Dreamcast : private DCHardware, public BaseBackend, public Filesys Graphics::PixelFormat getScreenFormat() const; // Returns a list of all pixel formats supported by the backend. - Common::List<Graphics::PixelFormat> getSupportedFormats(); + Common::List<Graphics::PixelFormat> getSupportedFormats() const; // Set the size of the video bitmap. // Typically, 320x200 diff --git a/backends/platform/dc/display.cpp b/backends/platform/dc/display.cpp index 35fc94b3cc..53dbff333d 100644 --- a/backends/platform/dc/display.cpp +++ b/backends/platform/dc/display.cpp @@ -198,7 +198,7 @@ Graphics::PixelFormat OSystem_Dreamcast::getScreenFormat() const return screenFormats[_screenFormat]; } -Common::List<Graphics::PixelFormat> OSystem_Dreamcast::getSupportedFormats() +Common::List<Graphics::PixelFormat> OSystem_Dreamcast::getSupportedFormats() const { Common::List<Graphics::PixelFormat> list; unsigned i; diff --git a/backends/platform/ds/arm7/source/main.cpp b/backends/platform/ds/arm7/source/main.cpp index a4cde02ba6..bcaaf8e936 100644 --- a/backends/platform/ds/arm7/source/main.cpp +++ b/backends/platform/ds/arm7/source/main.cpp @@ -8,17 +8,19 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * - * $Header: /cvsroot/scummvm/scummvm/backends/fs/fs.cpp,v 1.3.2.1 2004/12/18 02:33:52 fingolfin Exp $ */ ////////////////////////////////////////////////////////////////////// @@ -58,10 +60,10 @@ s32 TOUCH_HEIGHT = TOUCH_CAL_Y2 - TOUCH_CAL_Y1; s32 TOUCH_OFFSET_X = ( ((SCREEN_WIDTH -60) * TOUCH_CAL_X1) / TOUCH_WIDTH ) - 28; s32 TOUCH_OFFSET_Y = ( ((SCREEN_HEIGHT-60) * TOUCH_CAL_Y1) / TOUCH_HEIGHT ) - 28; -vu8* soundData; +vu8 *soundData; -vu8* soundBuffer; -vu8* arm9Buffer; +vu8 *soundBuffer; +vu8 *arm9Buffer; bool soundFilled[4]; int playingSection; @@ -81,7 +83,7 @@ int adpcmBufferNum = 0; ////////////////////////////////////////////////////////////////////// /* -void startSound(int sampleRate, const void* data, uint32 bytes, u8 channel=0, u8 vol=0x7F, u8 pan=63, u8 format=0) { +void startSound(int sampleRate, const void *data, uint32 bytes, u8 channel=0, u8 vol=0x7F, u8 pan=63, u8 format=0) { SCHANNEL_TIMER(channel) = SOUND_FREQ(sampleRate); SCHANNEL_SOURCE(channel) = (uint32)data; SCHANNEL_LENGTH(channel) = bytes; @@ -106,7 +108,7 @@ s8 getFreeSoundChannel() { return -1; } -void startSound(int sampleRate, const void* data, uint32 bytes, u8 channel=0, u8 vol=0x7F, u8 pan=63, u8 format=0) { +void startSound(int sampleRate, const void *data, uint32 bytes, u8 channel=0, u8 vol=0x7F, u8 pan=63, u8 format=0) { // REG_IME = IME_DISABLE; channel = getFreeSoundChannel(); @@ -177,7 +179,7 @@ void startSound(int sampleRate, const void* data, uint32 bytes, u8 channel=0, u8 - soundData = (vu8* ) data; + soundData = (vu8 *) data; SCHANNEL_CR(channel) = flags; SCHANNEL_CR(channel + 2) = flags; @@ -386,7 +388,7 @@ void InterruptTimer1() { //if ((!soundFilled[r]) && (!IPC->fillNeeded[playingSection])) { memcpy((void *) (soundBuffer + (r * 1024)), (void *) (arm9Buffer + (r * 1024)), 1024); - vu16* p = (vu16 *) (soundBuffer); + vu16 *p = (vu16 *) (soundBuffer); //for (int t = 0; t < 2048; t++) { // *(p + t) = (t & 1)? 0xF000: 0x0000; //} diff --git a/backends/platform/ds/arm9/makefile b/backends/platform/ds/arm9/makefile index 7f03f4c310..079e23aec0 100644 --- a/backends/platform/ds/arm9/makefile +++ b/backends/platform/ds/arm9/makefile @@ -113,9 +113,6 @@ ifdef DS_BUILD_A DEFINES = -DDS_SCUMM_BUILD -DDS_BUILD_A -DUSE_ARM_GFX_ASM -DUSE_ARM_COSTUME_ASM LOGO = logoa.bmp ENABLE_SCUMM = STATIC_PLUGIN - DEFINES += -DENABLE_SCUMM=STATIC_PLUGIN - MODULES += engines/scumm - USE_ARM_GFX_ASM = 1 BUILD=scummvm-A endif @@ -202,7 +199,6 @@ endif #endif ARM7BIN := -7 $(CURDIR)/../../arm7/arm7.bin -ICON := -b ../../../logo.bmp "ScummVM;By Neil Millstone;" CC = arm-eabi-gcc CXX = arm-eabi-g++ @@ -248,9 +244,6 @@ endif DEFINES += -DREDUCE_MEMORY_USAGE -# Removed, as these are done in portdefs.h -# -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE - LDFLAGS = -specs=ds_arm9.specs -mthumb-interwork -mno-fpu -Wl,-Map,map.txt -Wl,--gc-sections ifdef WRAP_MALLOC @@ -260,7 +253,7 @@ endif INCLUDES= -I$(portdir)/$(BUILD) -I$(srcdir) -I$(srcdir)/engines \ -I$(portdir)/data -I$(portdir)/../commoninclude \ - -I$(portdir)/source -I$(portdir)/source/mad -I$(portdir)/source/libcartreset \ + -I$(portdir)/source -I$(portdir)/source/mad \ -I$(libndsdir)/include -include $(srcdir)/common/scummsys.h @@ -272,12 +265,7 @@ ifdef USE_DEBUGGER LIBS += -ldsdebugger -ldswifi9 endif -#-Lscumm -lscumm -Lbase -lbase -Lcommon -lcommon -Lgraphics -lgraphics -Lgui -lgui -Lsound -lsound EXECUTABLE = scummvm.elf -PLUGIN_PREFIX = -PLUGIN_SUFFIX = .plg -PLUGIN_EXTRA_DEPS = plugin.x plugin.syms scummvm.elf -PLUGIN_LDFLAGS = -nostartfiles -Wl,-q,-Tplugin.x,--just-symbols,scummvm.elf,--retain-symbols-file,plugin.syms -L$(ronindir)/lib MKDIR = mkdir -p RM = rm -f RM_REC = rm -rf @@ -287,73 +275,69 @@ OBJCOPY = arm-eabi-objcopy AS = arm-eabi-as HAVE_GCC3 = true -ifdef DYNAMIC_MODULES -DEFINES += -DDYNAMIC_MODULES -PRE_OBJS_FLAGS = -Wl,--whole-archive -POST_OBJS_FLAGS = -Wl,--no-whole-archive -endif - -PORT_OBJS := $(portdir)/source/blitters_arm.o $(portdir)/source/cdaudio.o $(portdir)/source/dsmain.o \ - $(portdir)/../../../fs/ds/ds-fs.o $(portdir)/source/gbampsave.o $(portdir)/source/scummhelp.o\ - $(portdir)/source/osystem_ds.o $(portdir)/source/portdefs.o $(portdir)/source/ramsave.o\ - $(portdir)/source/touchkeyboard.o $(portdir)/source/zipreader.o\ - $(portdir)/source/dsoptions.o $(portdir)/source/keys.o $(portdir)/source/wordcompletion.o\ - $(portdir)/source/interrupt.o +PORT_OBJS := \ + $(portdir)/source/blitters_arm.o \ + $(portdir)/source/cdaudio.o \ + $(portdir)/source/dsmain.o \ + $(portdir)/../../../fs/ds/ds-fs.o \ + $(portdir)/source/gbampsave.o \ + $(portdir)/source/scummhelp.o \ + $(portdir)/source/osystem_ds.o \ + $(portdir)/source/touchkeyboard.o \ + $(portdir)/source/zipreader.o \ + $(portdir)/source/dsoptions.o \ + $(portdir)/source/keys.o \ + $(portdir)/source/wordcompletion.o \ + $(portdir)/source/interrupt.o ifdef USE_PROFILER PORT_OBJS += $(portdir)/source/profiler/cyg-profile.o endif -DATA_OBJS := $(portdir)/data/icons.o $(portdir)/data/keyboard.o $(portdir)/data/keyboard_pal.o $(portdir)/data/default_font.o $(portdir)/data/8x8font_tga.o - -COMPRESSOR_OBJS := -#$(portdir)/source/compressor/lz.o +DATA_OBJS := + $(portdir)/data/icons.o \ + $(portdir)/data/keyboard.o \ + $(portdir)/data/keyboard_pal.o \ + $(portdir)/data/default_font.o \ + $(portdir)/data/8x8font_tga.o + +FAT_OBJS := + $(portdir)/source/fat/disc_io.o \ + $(portdir)/source/fat/gba_nds_fat.o \ + $(portdir)/source/fat/io_fcsr.o \ + $(portdir)/source/fat/io_m3cf.o \ + $(portdir)/source/fat/io_mpcf.o \ + $(portdir)/source/fat/io_sccf.o \ + $(portdir)/source/fat/io_m3sd.o \ + $(portdir)/source/fat/io_nmmc.o \ + $(portdir)/source/fat/io_scsd.o \ + $(portdir)/source/fat/io_scsd_asm.o \ + $(portdir)/source/fat/io_njsd.o \ + $(portdir)/source/fat/io_mmcf.o \ + $(portdir)/source/fat/io_sd_common.o \ + $(portdir)/source/fat/io_m3_common.o \ + $(portdir)/source/fat/io_dldi.o \ + $(portdir)/source/fat/m3sd.o -FAT_OBJS := $(portdir)/source/fat/disc_io.o $(portdir)/source/fat/gba_nds_fat.o\ - $(portdir)/source/fat/io_fcsr.o $(portdir)/source/fat/io_m3cf.o\ - $(portdir)/source/fat/io_mpcf.o $(portdir)/source/fat/io_sccf.o\ - $(portdir)/source/fat/io_m3sd.o\ - $(portdir)/source/fat/io_nmmc.o $(portdir)/source/fat/io_scsd.o \ - $(portdir)/source/fat/io_scsd_asm.o \ - $(portdir)/source/fat/io_njsd.o \ - $(portdir)/source/fat/io_mmcf.o \ - $(portdir)/source/fat/io_sd_common.o \ - $(portdir)/source/fat/io_m3_common.o \ - $(portdir)/source/fat/io_dldi.o \ - $(portdir)/source/fat/m3sd.o - - -# $(portdir)/source/fat/io_cf_common.o $(portdir)/source/fat/io_m3_common.o\ -# $(portdir)/source/fat/io_sd_common.o $(portdir)/source/fat/io_scsd_s.o \ -# $(portdir)/source/fat/io_sc_common.o $(portdir)/source/fat/io_sd_common.o - -LIBCARTRESET_OBJS := -#$(portdir)/source/libcartreset/cartreset.o # Files in this list will be optimisied for speed, otherwise they will be optimised for space -OPTLIST := actor.cpp ds_main.cpp osystem_ds.cpp blitters.cpp mame.cpp rate.cpp isomap.cpp image.cpp gfx.cpp sprite.cpp actor_path.cpp actor_walk.cpp script.cpp +OPTLIST := actor.cpp dsmain.cpp osystem_ds.cpp blitters.cpp mame.cpp rate.cpp isomap.cpp image.cpp gfx.cpp sprite.cpp actor_path.cpp actor_walk.cpp script.cpp #OPTLIST := # Compiler options for files which should be optimised for speed ifdef DS_BUILD_E -# Another attempt to save some RAM in ITE -OPT_SPEED := -O3 -mthumb + # Another attempt to save some RAM in ITE + OPT_SPEED := -O3 -mthumb else -#OPT_SPEED := -O3 - -OPT_SPEED := -Os -mthumb - + OPT_SPEED := -O3 endif # Compiler options for files which should be optimised for space OPT_SIZE := -Os -mthumb -#-mthumb -fno-gcse -fno-schedule-insns2 - - -OBJS := $(DATA_OBJS) $(LIBCARTRESET_OBJS) $(PORT_OBJS) $(COMPRESSOR_OBJS) $(FAT_OBJS) +OBJS := $(DATA_OBJS) $(PORT_OBJS) $(FAT_OBJS) @@ -361,7 +345,7 @@ MODULE_DIRS += . ndsall: @[ -d $(BUILD) ] || mkdir -p $(BUILD) - make -C ./$(BUILD) -f ../makefile scummvm.nds + make -C ./$(BUILD) -f ../makefile scummvm.nds scummvm.ds.gba include $(srcdir)/Makefile.common @@ -372,25 +356,12 @@ clean: $(RM) $(OBJS) $(EXECUTABLE) rm -fr $(BUILD) -plugin_dist : - find . -name '*.plg' | while read p; do \ - sh-elf-strip -g -o "`basename \"$$p\" | tr '[:lower:]' '[:upper:]'`" "$$p"; \ - done - dist : SCUMMVM.BIN plugins plugin_dist #--------------------------------------------------------------------------------- # canned command sequence for binary data #--------------------------------------------------------------------------------- -#define bin2o -# bin2s $< | $(AS) -mthumb -mthumb-interwork -o $(@) -# echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_raw_end[];" > `(echo $(<F) | tr . _)`.h -# echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_raw[];" >> `(echo $(<F) | tr . _)`.h -# echo "extern const u32" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_raw_size";" >> `(echo $(<F) | tr . _)`.h -#endef - - define bin2o bin2s $< | $(AS) -mthumb -mthumb-interwork -o $(@) echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(<F) | tr . _)`.h @@ -399,34 +370,10 @@ define bin2o endef -#define bin2o -# @echo $(*) -# cp $(<) $(*).tmp -# $(OBJCOPY) -I binary -O elf32-littlearm -B arm \ -# --rename-section .data=.rodata \ -# --redefine-sym _binary_$(subst .,_,$(subst /,_,$(*)))_tmp_start=$(notdir $*)\ -# --redefine-sym _binary_$(subst .,_,$(subst /,_,$(*)))_tmp_end=$(notdir $*)_end\ -# $(*).tmp $(@) -# echo "extern const u8" $(notdir $*)"[] __attribute__ ((aligned (4)));" > $(*).h -# echo "extern const u32" $(notdir $(*))_size[]";" >> $(*).h -# -# echo $(*).h -# rm $(*).tmp -#endef - - ############## # Replacement rule for the one in makefile.common ############## %.o: %.cpp -# echo !!!!!!!!!!!! $(notdir $<) -# ifeq ( $(notdir $<), $(findstring $(notdir $<), $(OPTLIST)) ) -# OPTFLAG=-O3 -# else -# OPTFLAG=-Os -# endif -# export OPTFLAG = ; -# echo !!!!!!!! $(OPTFLAG) $(MKDIR) $(*D)/$(DEPDIR) $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(if $(findstring $(notdir $<), $(OPTLIST)), $(OPT_SPEED), $(OPT_SIZE)) $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o @@ -434,12 +381,6 @@ endef #--------------------------------------------------------------------------------- #--------------------------------------------------------------------------------- -%.o : %.pcx -#--------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) - -#--------------------------------------------------------------------------------- %.o : %.bin #--------------------------------------------------------------------------------- @echo $(notdir $<) @@ -458,30 +399,16 @@ endef @$(bin2o) #--------------------------------------------------------------------------------- -%.o : %.map -#--------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) - -#--------------------------------------------------------------------------------- -%.o : %.mdl -#--------------------------------------------------------------------------------- - @echo $(notdir $<) - @$(bin2o) - -#--------------------------------------------------------------------------------- %.nds: %.bin - @echo ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../../$(LOGO) "$(shell basename $@);ScummVM $(VERSION);DS Port" - ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../../$(LOGO) "$(shell basename $@);ScummVM $(VERSION);DS Port" - dsbuild $@ -l ../ndsloader.bin + ndstool -c $@ -9 $< $(ARM7BIN) -b ../../$(LOGO) "$(@F);ScummVM $(VERSION);DS Port" - padbin 16 $(basename $@).ds.gba +%.ds.gba: %.nds + dsbuild $< -o $@ -l $(portdir)/ndsloader.bin + padbin 16 $@ #--------------------------------------------------------------------------------- -# FIXME: The following rule hardcodes the input & output filename -- shouldn't it use $< and $@ instead? %.bin: %.elf - $(OBJCOPY) -S scummvm.elf scummvm-stripped.elf - $(OBJCOPY) -O binary scummvm-stripped.elf scummvm.bin + $(OBJCOPY) -S -O binary $< $@ #%.o: %.s # $(MKDIR) $(*D)/$(DEPDIR) diff --git a/backends/platform/ds/arm9/source/blitters.cpp b/backends/platform/ds/arm9/source/blitters.cpp index 07c6b3fee1..5d29672ef6 100644 --- a/backends/platform/ds/arm9/source/blitters.cpp +++ b/backends/platform/ds/arm9/source/blitters.cpp @@ -8,15 +8,18 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ @@ -27,13 +30,13 @@ namespace DS { -void asmDrawStripToScreen(int height, int width, byte const* text, byte const* src, byte* dst, +void asmDrawStripToScreen(int height, int width, byte const *text, byte const *src, byte *dst, int vsPitch, int vmScreenWidth, int textSurfacePitch) { - - if (height <= 0) height = 1; - if (width < 4) return; - + if (height <= 0) + height = 1; + if (width < 4) + return; width &= ~4; // src = (const byte *) (((int) (src)) & (~4)); @@ -111,7 +114,7 @@ void asmDrawStripToScreen(int height, int width, byte const* text, byte const* s -void asmCopy8Col(byte* dst, int dstPitch, const byte* src, int height) { +void asmCopy8Col(byte *dst, int dstPitch, const byte *src, int height) { asm("ands r0, %3, #1\n" "addne %3, %3, #1\n" "bne roll2\n" @@ -141,22 +144,19 @@ void asmCopy8Col(byte* dst, int dstPitch, const byte* src, int height) { static bool isDivBy5Ready = false; static u32 DIV_BY_5[160]; -void ComputeDivBy5TableIFN() -{ +void ComputeDivBy5TableIFN() { if (isDivBy5Ready) return; isDivBy5Ready = true; - for (int i=0; i<160; ++i) - { + for (int i = 0; i < 160; ++i) { DIV_BY_5[i] = (2*i+5)/10; } } #ifdef PERFECT_5_TO_4_RESCALING static inline void RescaleBlock_5x1555_To_4x1555( u16 s0, u16 s1, u16 s2, u16 s3, u16 s4, - u16* dest) -{ + u16 *dest) { u32 bs0 = s0 & 0x1F; u32 bs1 = s1 & 0x1F; u32 bs2 = s2 & 0x1F; @@ -230,8 +230,7 @@ static inline void RescaleBlock_5x1555_To_4x1555( u16 s0, u16 s1, u16 s2, u16 s3 } #else static inline void RescaleBlock_5x1555_To_4x1555( u16 s0, u16 s1, u16 s2, u16 s3, u16 s4, - u16* dest) -{ + u16 *dest) { static const u32 MASK = 0x03E07C1F; u32 argbargbs0 = u32(s0) | (u32(s0) << 16); @@ -279,8 +278,7 @@ static inline void RescaleBlock_5x1555_To_4x1555( u16 s0, u16 s1, u16 s2, u16 s3 #endif static inline void RescaleBlock_5x8888_To_4x1555( u32 s0, u32 s1, u32 s2, u32 s3, u32 s4, - u16* dest) -{ + u16 *dest) { u32 d0 = 4*s0 + s1; u32 d1 = 2*s1 + s1 + 2*s2; @@ -317,12 +315,10 @@ static inline void RescaleBlock_5x8888_To_4x1555( u32 s0, u32 s1, u32 s2, u32 s3 // Can't work in place #ifdef PERFECT_5_TO_4_RESCALING -static inline void Rescale_320xPAL8Scanline_To_256x1555Scanline(u16* dest, const u8* src, const u32* palette) -{ +static inline void Rescale_320xPAL8Scanline_To_256x1555Scanline(u16 *dest, const u8 *src, const u32 *palette) { ComputeDivBy5TableIFN(); - for (size_t i=0; i<64; ++i) - { + for (size_t i = 0; i < 64; ++i) { u32 s0 = palette[src[5*i+0]]; u32 s1 = palette[src[5*i+1]]; u32 s2 = palette[src[5*i+2]]; @@ -333,10 +329,8 @@ static inline void Rescale_320xPAL8Scanline_To_256x1555Scanline(u16* dest, const } } #else -static inline void Rescale_320xPAL8Scanline_To_256x1555Scanline(u16* dest, const u8* src, const u16* palette) -{ - for (size_t i=0; i<64; ++i) - { +static inline void Rescale_320xPAL8Scanline_To_256x1555Scanline(u16 *dest, const u8 *src, const u16 *palette) { + for (size_t i = 0; i < 64; ++i) { u16 s0 = palette[src[5*i+0]]; u16 s1 = palette[src[5*i+1]]; u16 s2 = palette[src[5*i+2]]; @@ -350,12 +344,10 @@ static inline void Rescale_320xPAL8Scanline_To_256x1555Scanline(u16* dest, const // Can work in place, because it's a contraction -static inline void Rescale_320x1555Scanline_To_256x1555Scanline(u16* dest, const u16* src) -{ +static inline void Rescale_320x1555Scanline_To_256x1555Scanline(u16 *dest, const u16 *src) { ComputeDivBy5TableIFN(); - for (size_t i=0; i<64; ++i) - { + for (size_t i = 0; i < 64; ++i) { u16 s0 = src[5*i+0]; u16 s1 = src[5*i+1]; u16 s2 = src[5*i+2]; @@ -367,13 +359,11 @@ static inline void Rescale_320x1555Scanline_To_256x1555Scanline(u16* dest, const } #ifdef PERFECT_5_TO_4_RESCALING -void Rescale_320x256xPAL8_To_256x256x1555(u16* dest, const u8* src, int destStride, int srcStride, const u16* palette) -{ +void Rescale_320x256xPAL8_To_256x256x1555(u16 *dest, const u8 *src, int destStride, int srcStride, const u16 *palette) { u32 fastRam[768]; // Palette lookup -> 0_888 - for (size_t i=0; i<256; ++i) - { + for (size_t i = 0; i < 256; ++i) { u32 col = palette[i]; u32 result = col & 0x0000001F; result |= (col << 3) & 0x00001F00; @@ -382,31 +372,26 @@ void Rescale_320x256xPAL8_To_256x256x1555(u16* dest, const u8* src, int destStri fastRam[i] = result; } - for (size_t i=0; i<200; ++i) - { + for (size_t i = 0; i < 200; ++i) { Rescale_320xPAL8Scanline_To_256x1555Scanline(dest + i*destStride, src + i *srcStride, fastRam); } } #else -void Rescale_320x256xPAL8_To_256x256x1555(u16* dest, const u8* src, int destStride, int srcStride, const u16* palette) -{ +void Rescale_320x256xPAL8_To_256x256x1555(u16 *dest, const u8 *src, int destStride, int srcStride, const u16 *palette) { u16 fastRam[256]; - for (size_t i=0; i<128; ++i) + for (size_t i = 0; i < 128; ++i) ((u32*)fastRam)[i] = ((const u32*)palette)[i]; - for (size_t i=0; i<200; ++i) - { + for (size_t i = 0; i < 200; ++i) { Rescale_320xPAL8Scanline_To_256x1555Scanline(dest + i*destStride, src + i *srcStride, fastRam); } } #endif -void Rescale_320x256x1555_To_256x256x1555(u16* dest, const u16* src, int destStride, int srcStride) -{ - for (size_t i=0; i<200; ++i) - { +void Rescale_320x256x1555_To_256x256x1555(u16 *dest, const u16 *src, int destStride, int srcStride) { + for (size_t i = 0; i < 200; ++i) { Rescale_320x1555Scanline_To_256x1555Scanline(dest + i*destStride, src + i *srcStride); } } -} +} // End of namespace DS diff --git a/backends/platform/ds/arm9/source/blitters.h b/backends/platform/ds/arm9/source/blitters.h index 5f541d1bd6..88506a4405 100644 --- a/backends/platform/ds/arm9/source/blitters.h +++ b/backends/platform/ds/arm9/source/blitters.h @@ -8,15 +8,18 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ @@ -29,23 +32,23 @@ namespace DS { -void asmDrawStripToScreen(int height, int width, byte const* text, byte const* src, byte* dst, +void asmDrawStripToScreen(int height, int width, byte const *text, byte const *src, byte *dst, int vsPitch, int vmScreenWidth, int textSurfacePitch); -void asmCopy8Col(byte* dst, int dstPitch, const byte* src, int height); -void Rescale_320x256xPAL8_To_256x256x1555(u16* dest, const u8* src, int destStride, int srcStride, const u16* palette); -void Rescale_320x256x1555_To_256x256x1555(u16* dest, const u16* src, int destStride, int srcStride); +void asmCopy8Col(byte *dst, int dstPitch, const byte *src, int height); +void Rescale_320x256xPAL8_To_256x256x1555(u16 *dest, const u8 *src, int destStride, int srcStride, const u16 *palette); +void Rescale_320x256x1555_To_256x256x1555(u16 *dest, const u16 *src, int destStride, int srcStride); -} +} // End of namespace DS #else extern "C" { -void ITCM_CODE asmDrawStripToScreen(int height, int width, byte const* text, byte const* src, byte* dst, +void ITCM_CODE asmDrawStripToScreen(int height, int width, byte const *text, byte const *src, byte *dst, int vsPitch, int vmScreenWidth, int textSurfacePitch); -void ITCM_CODE asmCopy8Col(byte* dst, int dstPitch, const byte* src, int height); -void ITCM_CODE Rescale_320x256xPAL8_To_256x256x1555(u16* dest, const u8* src, int destStride, int srcStride, const u16* palette, u32 numLines); -void ITCM_CODE Rescale_320x256x1555_To_256x256x1555(u16* dest, const u16* src, int destStride, int srcStride); +void ITCM_CODE asmCopy8Col(byte *dst, int dstPitch, const byte *src, int height); +void ITCM_CODE Rescale_320x256xPAL8_To_256x256x1555(u16 *dest, const u8 *src, int destStride, int srcStride, const u16 *palette, u32 numLines); +void ITCM_CODE Rescale_320x256x1555_To_256x256x1555(u16 *dest, const u16 *src, int destStride, int srcStride); } diff --git a/backends/platform/ds/arm9/source/cdaudio.cpp b/backends/platform/ds/arm9/source/cdaudio.cpp index 7756286117..5860dea4f2 100644 --- a/backends/platform/ds/arm9/source/cdaudio.cpp +++ b/backends/platform/ds/arm9/source/cdaudio.cpp @@ -8,15 +8,18 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ @@ -71,25 +74,25 @@ struct decoderFormat { unsigned char sample[1024]; } __attribute__ ((packed)); -bool active = false; -WaveHeader waveHeader; -Header blockHeader; -FILE* file; -int fillPos; -bool isPlayingFlag = false; +static bool s_active = false; +static WaveHeader waveHeader; +static Header blockHeader; +static FILE *s_file; +static int fillPos; +static bool isPlayingFlag = false; -s16* audioBuffer; -u32 sampleNum; -s16* decompressionBuffer; -int numLoops; -int blockCount; -int dataChunkStart; -int blocksLeft; -bool trackStartsAt2 = false; +static s16 *audioBuffer; +static u32 sampleNum; +static s16 *decompressionBuffer; +static int s_numLoops; +static int blockCount; +static int dataChunkStart; +static int blocksLeft; +static bool trackStartsAt2 = false; // These are from Microsoft's document on DVI ADPCM -const int stepTab[ 89 ] = { +static const int stepTab[ 89 ] = { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, @@ -103,7 +106,7 @@ const int stepTab[ 89 ] = { 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 }; -const int indexTab[ 16 ] = { -1, -1, -1, -1, 2, 4, 6, 8, +static const int indexTab[ 16 ] = { -1, -1, -1, -1, 2, 4, 6, 8, -1, -1, -1, -1, 2, 4, 6, 8 }; void playNextBlock(); @@ -115,11 +118,11 @@ void allocBuffers() { } void setActive(bool active) { - DS::CD::active = active; + s_active = active; } bool getActive() { - return active; + return s_active; } void playTrack(int track, int numLoops, int startFrame, int duration) { @@ -145,21 +148,21 @@ void playTrack(int track, int numLoops, int startFrame, int duration) { sprintf(str, "track%d.wav", track); fname = path + str; - file = DS::std_fopen(fname.c_str(), "rb"); + s_file = DS::std_fopen(fname.c_str(), "rb"); - if (!file) { + if (!s_file) { sprintf(str, "track%02d.wav", track); fname = path + str; - file = DS::std_fopen(fname.c_str(), "rb"); + s_file = DS::std_fopen(fname.c_str(), "rb"); } - if (!file) { + if (!s_file) { consolePrintf("Failed to open %s!\n", path.c_str()); return; } - DS::std_fread((const void *) &waveHeader, sizeof(waveHeader), 1, file); + DS::std_fread(&waveHeader, sizeof(waveHeader), 1, s_file); consolePrintf("File: %s\n", fname.c_str()); @@ -171,7 +174,7 @@ void playTrack(int track, int numLoops, int startFrame, int duration) { if ((waveHeader.fmtFormatTag != 17) && (waveHeader.fmtFormatTag != 20)) { consolePrintf("Wave file is in the wrong format! You must use IMA-ADPCM 4-bit mono.\n"); - DS::std_fclose(file); + DS::std_fclose(s_file); return; } @@ -183,14 +186,14 @@ void playTrack(int track, int numLoops, int startFrame, int duration) { // Skip chunks until we reach the data chunk chunkHeader chunk; - DS::std_fread((const void *) &chunk, sizeof(chunkHeader), 1, file); + DS::std_fread(&chunk, sizeof(chunkHeader), 1, s_file); while (!((chunk.name[0] == 'd') && (chunk.name[1] == 'a') && (chunk.name[2] == 't') && (chunk.name[3] == 'a'))) { - DS::std_fseek(file, chunk.size, SEEK_CUR); - DS::std_fread((const void *) &chunk, sizeof(chunkHeader), 1, file); + DS::std_fseek(s_file, chunk.size, SEEK_CUR); + DS::std_fread(&chunk, sizeof(chunkHeader), 1, s_file); } - dataChunkStart = DS::std_ftell(file); + dataChunkStart = DS::std_ftell(s_file); static bool started = false; @@ -234,14 +237,14 @@ void playTrack(int track, int numLoops, int startFrame, int duration) { // No need to seek if we're starting from the beginning if (block != 0) { - DS::std_fseek(file, dataChunkStart + block * waveHeader.fmtBlockAlign, SEEK_SET); + DS::std_fseek(s_file, dataChunkStart + block * waveHeader.fmtBlockAlign, SEEK_SET); // consolePrintf("Startframe: %d msec: %d (%d,%d)\n", startFrame, tenthssec, samples, block); } //decompressBlock(); playNextBlock(); - DS::CD::numLoops = numLoops; + s_numLoops = numLoops; } void update() { @@ -263,20 +266,20 @@ void decompressBlock() { do { - DS::std_fread((const void *) &blockHeader, sizeof(blockHeader), 1, file); + DS::std_fread(&blockHeader, sizeof(blockHeader), 1, s_file); - DS::std_fread(&block[0], waveHeader.fmtBlockAlign - sizeof(blockHeader), 1, file); + DS::std_fread(&block[0], waveHeader.fmtBlockAlign - sizeof(blockHeader), 1, s_file); - if (DS::std_feof(file) ) { + if (DS::std_feof(s_file)) { // Reached end of file, so loop - if ((numLoops == -1) || (numLoops > 1)) { + if ((s_numLoops == -1) || (s_numLoops > 1)) { // Seek file to first packet - if (numLoops != -1) { - numLoops--; + if (s_numLoops != -1) { + s_numLoops--; } - DS::std_fseek(file, dataChunkStart, SEEK_SET); + DS::std_fseek(s_file, dataChunkStart, SEEK_SET); loop = true; } else { // Fill decompression buffer with zeros to prevent glitching @@ -325,45 +328,30 @@ void decompressBlock() { int offset = 0; switch (7 - (r & 0x0007)) { - case 0: { - offset = (word & 0xF0000000) >> 28; - break; - } - - case 1: { - offset = (word & 0x0F000000) >> 24; - break; - } - - case 2: { - offset = (word & 0x00F00000) >> 20; - break; - } - - case 3: { - offset = (word & 0x000F0000) >> 16; - break; - } - - case 4: { - offset = (word & 0x0000F000) >> 12; - break; - } - - case 5: { - offset = (word & 0x00000F00) >> 8; - break; - } - - case 6: { - offset = (word & 0x000000F0) >> 4; - break; - } - - case 7: { - offset = (word & 0x0000000F); - break; - } + case 0: + offset = (word & 0xF0000000) >> 28; + break; + case 1: + offset = (word & 0x0F000000) >> 24; + break; + case 2: + offset = (word & 0x00F00000) >> 20; + break; + case 3: + offset = (word & 0x000F0000) >> 16; + break; + case 4: + offset = (word & 0x0000F000) >> 12; + break; + case 5: + offset = (word & 0x00000F00) >> 8; + break; + case 6: + offset = (word & 0x000000F0) >> 4; + break; + case 7: + offset = (word & 0x0000000F); + break; } int diff = 0; @@ -406,7 +394,8 @@ void decompressBlock() { } void playNextBlock() { - if (!isPlayingFlag) return; + if (!isPlayingFlag) + return; int lastBlockId = -1; while (IPC->adpcm.semaphore); // Wait for buffer to become free if needed @@ -442,9 +431,6 @@ void playNextBlock() { // DC_FlushAll(); } - - - } @@ -460,9 +446,10 @@ void playNextBlock() { } void stopTrack() { - if (!isPlayingFlag) return; + if (!isPlayingFlag) + return; - DS::std_fclose(file); + DS::std_fclose(s_file); isPlayingFlag = false; @@ -470,7 +457,7 @@ void stopTrack() { audioBuffer[r] = 0; } - for (int r= 0; r < waveHeader.fmtExtra; r++) { + for (int r = 0; r < waveHeader.fmtExtra; r++) { decompressionBuffer[r] = 0; } // DS::stopSound(1); @@ -495,8 +482,8 @@ bool trackExists(int num) { } consolePrintf("Looking for %s...", path.c_str()); - FILE* file; - if ((file = DS::std_fopen(path.c_str(), "r"))) { + FILE *file = DS::std_fopen(path.c_str(), "r"); + if (file) { consolePrintf("Success!\n"); setActive(true); DS::std_fclose(file); @@ -548,4 +535,4 @@ bool isPlaying() { } } -} +} // End of namespace DS diff --git a/backends/platform/ds/arm9/source/cdaudio.h b/backends/platform/ds/arm9/source/cdaudio.h index aac303dd5e..6e53ef7bd2 100644 --- a/backends/platform/ds/arm9/source/cdaudio.h +++ b/backends/platform/ds/arm9/source/cdaudio.h @@ -8,15 +8,18 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ @@ -35,6 +38,6 @@ bool isPlaying(); void update(); } -} +} // End of namespace DS #endif diff --git a/backends/platform/ds/arm9/source/compressor/lz.cpp b/backends/platform/ds/arm9/source/compressor/lz.cpp deleted file mode 100644 index 47a36646c6..0000000000 --- a/backends/platform/ds/arm9/source/compressor/lz.cpp +++ /dev/null @@ -1,539 +0,0 @@ -/************************************************************************* -* Name: lz.c -* Author: Marcus Geelnard -* Description: LZ77 coder/decoder implementation. -* Reentrant: Yes -* $Id$ -* -* The LZ77 compression scheme is a substitutional compression scheme -* proposed by Abraham Lempel and Jakob Ziv in 1977. It is very simple in -* its design, and uses no fancy bit level compression. -* -* This is my first attempt at an implementation of a LZ77 code/decoder. -* -* The principle of the LZ77 compression algorithm is to store repeated -* occurrences of strings as references to previous occurrences of the same -* string. The point is that the reference consumes less space than the -* string itself, provided that the string is long enough (in this -* implementation, the string has to be at least 4 bytes long, since the -* minimum coded reference is 3 bytes long). Also note that the term -* "string" refers to any kind of byte sequence (it does not have to be -* an ASCII string, for instance). -* -* The coder uses a brute force approach to finding string matches in the -* history buffer (or "sliding window", if you wish), which is very, very -* slow. I recon the complexity is somewhere between O(n^2) and O(n^3), -* depending on the input data. -* -* There is also a faster implementation that uses a large working buffer -* in which a "jump table" is stored, which is used to quickly find -* possible string matches (see the source code for LZ_CompressFast() for -* more information). The faster method is an order of magnitude faster, -* and also does a full string search in the entire input buffer (it does -* not use a sliding window). -* -* The upside is that decompression is very fast, and the compression ratio -* is often very good. -* -* The reference to a string is coded as a (length,offset) pair, where the -* length indicates the length of the string, and the offset gives the -* offset from the current data position. To distinguish between string -* references and literal strings (uncompressed bytes), a string reference -* is preceded by a marker byte, which is chosen as the least common byte -* symbol in the input data stream (this marker byte is stored in the -* output stream as the first byte). -* -* Occurrences of the marker byte in the stream are encoded as the marker -* byte followed by a zero byte, which means that occurrences of the marker -* byte have to be coded with two bytes. -* -* The lengths and offsets are coded in a variable length fashion, allowing -* values of any magnitude (up to 4294967295 in this implementation). -* -* With this compression scheme, the worst case compression result is -* (257/256)*insize + 1. -* -*------------------------------------------------------------------------- -* Copyright (c) 2003-2004 Marcus Geelnard -* -* This software is provided 'as-is', without any express or implied -* warranty. In no event will the authors be held liable for any damages -* arising from the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software -* in a product, an acknowledgment in the product documentation would -* be appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not -* be misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source -* distribution. -* -* Marcus Geelnard -* marcus.geelnard at home.se -*************************************************************************/ - - -/************************************************************************* -* Constants used for LZ77 coding -*************************************************************************/ - -/* Maximum offset (can be any size < 2^32). Lower values gives faster - compression, while higher values gives better compression. - NOTE: LZ_CompressFast does not use this constant. */ -#define LZ_MAX_OFFSET 512 - - - -/************************************************************************* -* INTERNAL FUNCTIONS * -*************************************************************************/ - - -/************************************************************************* -* _LZ_StringCompare() - Return maximum length string match. -*************************************************************************/ - -inline static unsigned int _LZ_StringCompare( unsigned char * str1, - unsigned char * str2, unsigned int minlen, unsigned int maxlen ) -{ - unsigned int len; - - for ( len = minlen; (len < maxlen) && (str1[len] == str2[len]); ++ len ); - - return len; -} - - -/************************************************************************* -* _LZ_WriteVarSize() - Write unsigned integer with variable number of -* bytes depending on value. -*************************************************************************/ - -inline static int _LZ_WriteVarSize( unsigned int x, unsigned char * buf ) -{ - unsigned int y; - int num_bytes, i, b; - - /* Determine number of bytes needed to store the number x */ - y = x >> 3; - for ( num_bytes = 5; num_bytes >= 2; -- num_bytes ) - { - if ( y & 0xfe000000 ) break; - y <<= 7; - } - - /* Write all bytes, seven bits in each, with 8:th bit set for all */ - /* but the last byte. */ - for ( i = num_bytes-1; i >= 0; -- i ) - { - b = (x >> (i*7)) & 0x0000007f; - if ( i > 0 ) - { - b |= 0x00000080; - } - *buf ++ = (unsigned char) b; - } - - /* Return number of bytes written */ - return num_bytes; -} - - -/************************************************************************* -* _LZ_ReadVarSize() - Read unsigned integer with variable number of -* bytes depending on value. -*************************************************************************/ - -inline static int _LZ_ReadVarSize( unsigned int * x, unsigned char * buf ) -{ - unsigned int y, b, num_bytes; - - /* Read complete value (stop when byte contains zero in 8:th bit) */ - y = 0; - num_bytes = 0; - do - { - b = (unsigned int) (*buf ++); - y = (y << 7) | (b & 0x0000007f); - ++ num_bytes; - } - while ( b & 0x00000080 ); - - /* Store value in x */ - *x = y; - - /* Return number of bytes read */ - return num_bytes; -} - - - -/************************************************************************* -* PUBLIC FUNCTIONS * -*************************************************************************/ - - -/************************************************************************* -* LZ_Compress() - Compress a block of data using an LZ77 coder. -* in - Input (uncompressed) buffer. -* out - Output (compressed) buffer. This buffer must be 0.4% larger -* than the input buffer, plus one byte. -* insize - Number of input bytes. -* The function returns the size of the compressed data. -*************************************************************************/ - -int LZ_Compress( unsigned char *in, unsigned char *out, - unsigned int insize ) -{ - unsigned char marker, symbol; - unsigned int inpos, outpos, bytesleft, i; - unsigned int maxoffset, offset, bestoffset; - unsigned int maxlength, length, bestlength; - unsigned int histogram[ 256 ]; - unsigned char *ptr1, *ptr2; - - /* Do we have anything to compress? */ - if ( insize < 1 ) - { - return 0; - } - - /* Create histogram */ - for ( i = 0; i < 256; ++ i ) - { - histogram[ i ] = 0; - } - for ( i = 0; i < insize; ++ i ) - { - ++ histogram[ in[ i ] ]; - } - - /* Find the least common byte, and use it as the code marker */ - marker = 0; - for ( i = 1; i < 256; ++ i ) - { - if ( histogram[ i ] < histogram[ marker ] ) - { - marker = i; - } - } - - /* Remember the repetition marker for the decoder */ - out[ 0 ] = marker; - - /* Start of compression */ - inpos = 0; - outpos = 1; - - /* Main compression loop */ - bytesleft = insize; - do - { - /* Determine most distant position */ - if ( inpos > LZ_MAX_OFFSET ) maxoffset = LZ_MAX_OFFSET; - else maxoffset = inpos; - - /* Get pointer to current position */ - ptr1 = &in[ inpos ]; - - /* Search history window for maximum length string match */ - bestlength = 3; - bestoffset = 0; - for ( offset = 3; offset <= maxoffset; ++ offset ) - { - /* Get pointer to candidate string */ - ptr2 = &ptr1[ -offset ]; - - /* Quickly determine if this is a candidate (for speed) */ - if ( (ptr1[ 0 ] == ptr2[ 0 ]) && - (ptr1[ bestlength ] == ptr2[ bestlength ]) ) - { - /* Determine maximum length for this offset */ - maxlength = (bytesleft < offset ? bytesleft : offset); - - /* Count maximum length match at this offset */ - length = _LZ_StringCompare( ptr1, ptr2, 0, maxlength ); - - /* Better match than any previous match? */ - if ( length > bestlength ) - { - bestlength = length; - bestoffset = offset; - } - } - } - - /* Was there a good enough match? */ - if ( (bestlength >= 8) || - ((bestlength == 4) && (bestoffset <= 0x0000007f)) || - ((bestlength == 5) && (bestoffset <= 0x00003fff)) || - ((bestlength == 6) && (bestoffset <= 0x001fffff)) || - ((bestlength == 7) && (bestoffset <= 0x0fffffff)) ) - { - out[ outpos ++ ] = (unsigned char) marker; - outpos += _LZ_WriteVarSize( bestlength, &out[ outpos ] ); - outpos += _LZ_WriteVarSize( bestoffset, &out[ outpos ] ); - inpos += bestlength; - bytesleft -= bestlength; - } - else - { - /* Output single byte (or two bytes if marker byte) */ - symbol = in[ inpos ++ ]; - out[ outpos ++ ] = symbol; - if ( symbol == marker ) - { - out[ outpos ++ ] = 0; - } - -- bytesleft; - } - } - while ( bytesleft > 3 ); - - /* Dump remaining bytes, if any */ - while ( inpos < insize ) - { - if ( in[ inpos ] == marker ) - { - out[ outpos ++ ] = marker; - out[ outpos ++ ] = 0; - } - else - { - out[ outpos ++ ] = in[ inpos ]; - } - ++ inpos; - } - - return outpos; -} - - -/************************************************************************* -* LZ_CompressFast() - Compress a block of data using an LZ77 coder. -* in - Input (uncompressed) buffer. -* out - Output (compressed) buffer. This buffer must be 0.4% larger -* than the input buffer, plus one byte. -* insize - Number of input bytes. -* work - Pointer to a temporary buffer (internal working buffer), which -* must be able to hold (insize+65536) unsigned integers. -* The function returns the size of the compressed data. -*************************************************************************/ - -int LZ_CompressFast( unsigned char *in, unsigned char *out, - unsigned int insize, unsigned int *work ) -{ - unsigned char marker, symbol; - unsigned int inpos, outpos, bytesleft, i, index, symbols; - unsigned int offset, bestoffset; - unsigned int maxlength, length, bestlength; - unsigned int histogram[ 256 ], *lastindex, *jumptable; - unsigned char *ptr1, *ptr2; - - /* Do we have anything to compress? */ - if ( insize < 1 ) - { - return 0; - } - - /* Assign arrays to the working area */ - lastindex = work; - jumptable = &work[ 65536 ]; - - /* Build a "jump table". Here is how the jump table works: - jumptable[i] points to the nearest previous occurrence of the same - symbol pair as in[i]:in[i+1], so in[i] == in[jumptable[i]] and - in[i+1] == in[jumptable[i]+1]. Following the jump table gives a - dramatic boost for the string search'n'match loop compared to doing - a brute force search. */ - for ( i = 0; i < 65536; ++ i ) - { - lastindex[ i ] = 0xffffffff; - } - for ( i = 0; i < insize-1; ++ i ) - { - symbols = (((unsigned int)in[i]) << 8) | ((unsigned int)in[i+1]); - index = lastindex[ symbols ]; - lastindex[ symbols ] = i; - jumptable[ i ] = index; - } - jumptable[ insize-1 ] = 0xffffffff; - - /* Create histogram */ - for ( i = 0; i < 256; ++ i ) - { - histogram[ i ] = 0; - } - for ( i = 0; i < insize; ++ i ) - { - ++ histogram[ in[ i ] ]; - } - - /* Find the least common byte, and use it as the code marker */ - marker = 0; - for ( i = 1; i < 256; ++ i ) - { - if ( histogram[ i ] < histogram[ marker ] ) - { - marker = i; - } - } - - /* Remember the repetition marker for the decoder */ - out[ 0 ] = marker; - - /* Start of compression */ - inpos = 0; - outpos = 1; - - /* Main compression loop */ - bytesleft = insize; - do - { - /* Get pointer to current position */ - ptr1 = &in[ inpos ]; - - /* Search history window for maximum length string match */ - bestlength = 3; - bestoffset = 0; - index = jumptable[ inpos ]; - while ( index != 0xffffffff ) - { - /* Get pointer to candidate string */ - ptr2 = &in[ index ]; - - /* Quickly determine if this is a candidate (for speed) */ - if ( ptr2[ bestlength ] == ptr1[ bestlength ] ) - { - /* Determine maximum length for this offset */ - offset = inpos - index; - maxlength = (bytesleft < offset ? bytesleft : offset); - - /* Count maximum length match at this offset */ - length = _LZ_StringCompare( ptr1, ptr2, 2, maxlength ); - - /* Better match than any previous match? */ - if ( length > bestlength ) - { - bestlength = length; - bestoffset = offset; - } - } - - /* Get next possible index from jump table */ - index = jumptable[ index ]; - } - - /* Was there a good enough match? */ - if ( (bestlength >= 8) || - ((bestlength == 4) && (bestoffset <= 0x0000007f)) || - ((bestlength == 5) && (bestoffset <= 0x00003fff)) || - ((bestlength == 6) && (bestoffset <= 0x001fffff)) || - ((bestlength == 7) && (bestoffset <= 0x0fffffff)) ) - { - out[ outpos ++ ] = (unsigned char) marker; - outpos += _LZ_WriteVarSize( bestlength, &out[ outpos ] ); - outpos += _LZ_WriteVarSize( bestoffset, &out[ outpos ] ); - inpos += bestlength; - bytesleft -= bestlength; - } - else - { - /* Output single byte (or two bytes if marker byte) */ - symbol = in[ inpos ++ ]; - out[ outpos ++ ] = symbol; - if ( symbol == marker ) - { - out[ outpos ++ ] = 0; - } - -- bytesleft; - } - } - while ( bytesleft > 3 ); - - /* Dump remaining bytes, if any */ - while ( inpos < insize ) - { - if ( in[ inpos ] == marker ) - { - out[ outpos ++ ] = marker; - out[ outpos ++ ] = 0; - } - else - { - out[ outpos ++ ] = in[ inpos ]; - } - ++ inpos; - } - - return outpos; -} - - -/************************************************************************* -* LZ_Uncompress() - Uncompress a block of data using an LZ77 decoder. -* in - Input (compressed) buffer. -* out - Output (uncompressed) buffer. This buffer must be large -* enough to hold the uncompressed data. -* insize - Number of input bytes. -*************************************************************************/ - -void LZ_Uncompress( unsigned char *in, unsigned char *out, - unsigned int insize ) -{ - unsigned char marker, symbol; - unsigned int i, inpos, outpos, length, offset; - - /* Do we have anything to compress? */ - if ( insize < 1 ) - { - return; - } - - /* Get marker symbol from input stream */ - marker = in[ 0 ]; - inpos = 1; - - /* Main decompression loop */ - outpos = 0; - do - { - symbol = in[ inpos ++ ]; - if ( symbol == marker ) - { - /* We had a marker byte */ - if ( in[ inpos ] == 0 ) - { - /* It was a single occurrence of the marker byte */ - out[ outpos ++ ] = marker; - ++ inpos; - } - else - { - /* Extract true length and offset */ - inpos += _LZ_ReadVarSize( &length, &in[ inpos ] ); - inpos += _LZ_ReadVarSize( &offset, &in[ inpos ] ); - - /* Copy corresponding data from history window */ - for ( i = 0; i < length; ++ i ) - { - out[ outpos ] = out[ outpos - offset ]; - ++ outpos; - } - } - } - else - { - /* No marker, plain copy */ - out[ outpos ++ ] = symbol; - } - } - while ( inpos < insize ); -} diff --git a/backends/platform/ds/arm9/source/compressor/lz.h b/backends/platform/ds/arm9/source/compressor/lz.h deleted file mode 100644 index e7ea1567ca..0000000000 --- a/backends/platform/ds/arm9/source/compressor/lz.h +++ /dev/null @@ -1,50 +0,0 @@ -/************************************************************************* -* Name: lz.h -* Author: Marcus Geelnard -* Description: LZ77 coder/decoder interface. -* Reentrant: Yes -* $Id$ -*------------------------------------------------------------------------- -* Copyright (c) 2003-2004 Marcus Geelnard -* -* This software is provided 'as-is', without any express or implied -* warranty. In no event will the authors be held liable for any damages -* arising from the use of this software. -* -* Permission is granted to anyone to use this software for any purpose, -* including commercial applications, and to alter it and redistribute it -* freely, subject to the following restrictions: -* -* 1. The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software -* in a product, an acknowledgment in the product documentation would -* be appreciated but is not required. -* -* 2. Altered source versions must be plainly marked as such, and must not -* be misrepresented as being the original software. -* -* 3. This notice may not be removed or altered from any source -* distribution. -* -* Marcus Geelnard -* marcus.geelnard at home.se -*************************************************************************/ - -#ifndef _lz_h_ -#define _lz_h_ - - - -/************************************************************************* -* Function prototypes -*************************************************************************/ - -int LZ_Compress( unsigned char *in, unsigned char *out, - unsigned int insize ); -int LZ_CompressFast( unsigned char *in, unsigned char *out, - unsigned int insize, unsigned int *work ); -void LZ_Uncompress( unsigned char *in, unsigned char *out, - unsigned int insize ); - - -#endif /* _lz_h_ */ diff --git a/backends/platform/ds/arm9/source/dsmain.cpp b/backends/platform/ds/arm9/source/dsmain.cpp index 5a63e5f08f..95bfdfe40a 100644 --- a/backends/platform/ds/arm9/source/dsmain.cpp +++ b/backends/platform/ds/arm9/source/dsmain.cpp @@ -8,15 +8,18 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ @@ -70,8 +73,6 @@ -//#define USE_LIBCARTRESET - #include <nds.h> #include <nds/registers_alt.h> #include <nds/arm9/exceptions.h> @@ -80,8 +81,10 @@ //#include <ARM9/console.h> //basic print funcionality #include <stdlib.h> +#include <string.h> + +#include "NDS/scummvm_ipc.h" #include "dsmain.h" -#include "string.h" #include "osystem_ds.h" #include "icons_raw.h" #include "fat/gba_nds_fat.h" @@ -95,19 +98,19 @@ #ifdef USE_DEBUGGER #include "user_debugger.h" #endif -#include "ramsave.h" #include "blitters.h" -#include "cartreset_nolibfat.h" #include "keys.h" #ifdef USE_PROFILER #include "profiler/cyg-profile.h" #endif +#include "engine.h" + #include "backends/fs/ds/ds-fs.h" #include "base/version.h" -#include "engine.h" +#include "common/util.h" extern "C" void OurIntrMain(void); -extern "C" u32 getExceptionAddress( u32 opcodeAddress, u32 thumbState); +extern "C" u32 getExceptionAddress(u32 opcodeAddress, u32 thumbState); extern const char __itcm_start[]; static const char *registerNames[] = @@ -116,22 +119,20 @@ static const char *registerNames[] = #ifdef WRAP_MALLOC -extern "C" void* __real_malloc(size_t size); +extern "C" void *__real_malloc(size_t size); -int total = 0; +static int s_total_malloc = 0; -void* operator new (size_t size) -{ +void *operator new (size_t size) { register unsigned int reg asm("lr"); volatile unsigned int poo = reg; - void* res = __real_malloc(size); - total += size; + void *res = __real_malloc(size); + s_total_malloc += size; - if (!res) - { + if (!res) { // *((u8 *) NULL) = 0; - consolePrintf("Failed alloc (new) %d (%d)\n", size, total); + consolePrintf("Failed alloc (new) %d (%d)\n", size, s_total_malloc); return NULL; } @@ -139,7 +140,7 @@ void* operator new (size_t size) } -extern "C" void* __wrap_malloc(size_t size) { +extern "C" void *__wrap_malloc(size_t size) { /* u32 addr; asm("mov %0, lr" @@ -151,23 +152,22 @@ extern "C" void* __wrap_malloc(size_t size) { volatile unsigned int poo = reg; - if (size == 0) - { + if (size == 0) { static int zeroSize = 0; consolePrintf("0 size malloc (%d)", zeroSize++); } - void* res = __real_malloc(size); + void *res = __real_malloc(size); if (res) { if (size > 50 * 1024) { consolePrintf("Allocated %d (%x)\n", size, poo); } - total += size; + s_total_malloc += size; return res; } else { // *((u8 *) NULL) = 0; - consolePrintf("Failed alloc %d (%d)\n", size, total); + consolePrintf("Failed alloc %d (%d)\n", size, s_total_malloc); return NULL; } } @@ -193,112 +193,109 @@ enum MouseMode { #define SCUMM_GAME_HEIGHT 142 #define SCUMM_GAME_WIDTH 227 -int textureID; -u16* texture; - -int frameCount; -int currentTimeMillis; +static int frameCount; +static int currentTimeMillis; // Timer Callback -int callbackInterval; -int callbackTimer; -OSystem_DS::TimerProc callback; +static int callbackInterval; +static int callbackTimer; +static OSystem_DS::TimerProc callback; // Scaled -bool scaledMode; -int scX; -int scY; +static bool scaledMode; +static int scX; +static int scY; -int subScX; -int subScY; -int subScTargetX; -int subScTargetY; -int subScreenWidth = SCUMM_GAME_WIDTH; -int subScreenHeight = SCUMM_GAME_HEIGHT; -int subScreenScale = 256; +static int subScX; +static int subScY; +static int subScTargetX; +static int subScTargetY; +static int subScreenWidth = SCUMM_GAME_WIDTH; +static int subScreenHeight = SCUMM_GAME_HEIGHT; +static int subScreenScale = 256; // Sound -int bufferSize; -s16* soundBuffer; -int bufferFrame; -int bufferRate; -int bufferSamples; -bool soundHiPart; -int soundFrequency; +static int bufferSize; +static s16 *soundBuffer; +static int bufferFrame; +static int bufferRate; +static int bufferSamples; +static bool soundHiPart; +static int soundFrequency; // Events -int lastEventFrame; -bool indyFightState; -bool indyFightRight; +static int lastEventFrame; +static bool indyFightState; +static bool indyFightRight; -OSystem_DS::SoundProc soundCallback; -void* soundParam; -int lastCallbackFrame; -bool bufferFirstHalf; -bool bufferSecondHalf; +static OSystem_DS::SoundProc soundCallback; +static int lastCallbackFrame; +static bool bufferFirstHalf; +static bool bufferSecondHalf; // Saved buffers -bool highBuffer; -bool displayModeIs8Bit = false; +static bool highBuffer; +static bool displayModeIs8Bit = false; // Game id -u8 gameID; +static u8 gameID; -bool snapToBorder = false; -bool consoleEnable = false; -bool gameScreenSwap = false; +static bool snapToBorder = false; +static bool consoleEnable = false; +static bool gameScreenSwap = false; bool isCpuScalerEnabled(); //#define HEAVY_LOGGING -MouseMode mouseMode = MOUSE_LEFT; +static MouseMode mouseMode = MOUSE_LEFT; -int storedMouseX = 0; -int storedMouseY = 0; +static int storedMouseX = 0; +static int storedMouseY = 0; // Sprites -SpriteEntry sprites[128]; -SpriteEntry spritesMain[128]; -int tweak; +static SpriteEntry sprites[128]; +static SpriteEntry spritesMain[128]; +static int tweak; // Shake -int shakePos = 0; +static int s_shakePos = 0; // Keyboard -bool keyboardEnable = false; -bool leftHandedMode = false; -bool keyboardIcon = false; +static bool keyboardEnable = false; +static bool leftHandedMode = false; +static bool keyboardIcon = false; // Touch -int touchScX, touchScY, touchX, touchY; -int mouseHotspotX, mouseHotspotY; -bool cursorEnable = false; -bool mouseCursorVisible = true; -bool rightButtonDown = false; -bool touchPadStyle = false; -int touchPadSensitivity = 8; -bool tapScreenClicks = true; - -int tapCount = 0; -int tapTimeout = 0; -int tapComplete = 0; +static int touchScX, touchScY, touchX, touchY; +static int mouseHotspotX, mouseHotspotY; +static bool cursorEnable = false; +static bool mouseCursorVisible = true; +static bool leftButtonDown = false; +static bool rightButtonDown = false; +static bool touchPadStyle = false; +static int touchPadSensitivity = 8; +static bool tapScreenClicks = true; + +static int tapCount = 0; +static int tapTimeout = 0; +static int tapComplete = 0; // Dragging -int dragStartX, dragStartY; -bool dragging = false; -int dragScX, dragScY; +static int dragStartX, dragStartY; +static bool dragging = false; +static int dragScX, dragScY; // Interface styles -char gameName[32]; +static char gameName[32]; // 8-bit surface size -int gameWidth = 320; -int gameHeight = 200; +static int gameWidth = 320; +static int gameHeight = 200; // Scale -bool twoHundredPercentFixedScale = false; -bool cpuScalerEnable = false; +static bool twoHundredPercentFixedScale = false; +static bool cpuScalerEnable = false; // 100 256 // 150 192 @@ -309,14 +306,14 @@ bool cpuScalerEnable = false; #ifdef USE_PROFILER -int hBlankCount = 0; +static int hBlankCount = 0; #endif -u8* scalerBackBuffer = NULL; +static u8 *scalerBackBuffer = NULL; #define NUM_SUPPORTED_GAMES 21 -gameListType gameList[NUM_SUPPORTED_GAMES] = { +static const gameListType gameList[NUM_SUPPORTED_GAMES] = { // Unknown game - use normal SCUMM controls {"unknown", CONT_SCUMM_ORIGINAL}, @@ -345,31 +342,29 @@ gameListType gameList[NUM_SUPPORTED_GAMES] = { {"parallaction", CONT_NIPPON}, }; -gameListType* currentGame = NULL; +static const gameListType *s_currentGame = NULL; // Stylus -#define ABS(x) ((x)>0?(x):-(x)) - -bool penDown = FALSE; -bool penHeld = FALSE; -bool penReleased = FALSE; -bool penDownLastFrame = FALSE; -s32 penX = 0, penY = 0; -s32 penDownX = 0, penDownY = 0; -int keysDownSaved = 0; -int keysReleasedSaved = 0; -int keysChangedSaved = 0; +static bool penDown = FALSE; +static bool penHeld = FALSE; +static bool penReleased = FALSE; +static bool penDownLastFrame = FALSE; +static s32 penX = 0, penY = 0; +static s32 penDownX = 0, penDownY = 0; +static int keysDownSaved = 0; +static int keysReleasedSaved = 0; +static int keysChangedSaved = 0; -bool penDownSaved = FALSE; -bool penReleasedSaved = FALSE; -int penDownFrames = 0; -int touchXOffset = 0; -int touchYOffset = 0; +static bool penDownSaved = FALSE; +static bool penReleasedSaved = FALSE; +static int penDownFrames = 0; +static int touchXOffset = 0; +static int touchYOffset = 0; -int triggeredIcon = 0; -int triggeredIconTimeout = 0; +static int triggeredIcon = 0; +static int triggeredIconTimeout = 0; -u16 savedPalEntry255 = RGB15(31, 31, 31); +static u16 savedPalEntry255 = RGB15(31, 31, 31); extern "C" int scummvm_main(int argc, char *argv[]); @@ -382,8 +377,11 @@ void setIcon(int num, int x, int y, int imageNum, int flags, bool enable); void setIconMain(int num, int x, int y, int imageNum, int flags, bool enable); void uploadSpriteGfx(); -TransferSound soundControl; +static TransferSound soundControl; +static bool isScrollingWithDPad() { + return (getKeysHeld() & (KEY_L | KEY_R)) != 0; +} bool isCpuScalerEnabled() { return cpuScalerEnable || !displayModeIs8Bit; @@ -430,12 +428,12 @@ void setTopScreenZoom(int percentage) { // return (ConfMan.hasKey("cpu_scaler", "ds") && ConfMan.getBool("cpu_scaler", "ds")); controlType getControlType() { - return currentGame->control; + return s_currentGame->control; } //plays an 8 bit mono sample at 11025Hz -void playSound(const void* data, u32 length, bool loop, bool adpcm, int rate) { +void playSound(const void *data, u32 length, bool loop, bool adpcm, int rate) { if (!IPC->soundData) { soundControl.count = 0; @@ -551,21 +549,8 @@ int getSoundFrequency() { return soundFrequency; } -void setControls(char* gameName) { - - for (int r = 0; r < NUM_SUPPORTED_GAMES; r++) { - if (!stricmp(gameName, gameList[r].gameId)) { - currentGame = &gameList[r]; - consolePrintf("Current game set to: %s\n", gameName); - return; - } - } - - consolePrintf("Failed to set current game to: %s\n", gameName); -} - void exitGame() { - currentGame = NULL; + s_currentGame = NULL; } void initGame() { @@ -580,17 +565,17 @@ void initGame() { setOptions(); //strcpy(gameName, ConfMan.getActiveDomain().c_str()); - if (currentGame == NULL) { + if (s_currentGame == NULL) { strcpy(gameName, ConfMan.get("gameid").c_str()); // consolePrintf("\n\n\n\nCurrent game: '%s' %d\n", gameName, gameName[0]); - currentGame = &gameList[0]; // Default game + s_currentGame = &gameList[0]; // Default game for (int r = 0; r < NUM_SUPPORTED_GAMES; r++) { if (!stricmp(gameName, gameList[r].gameId)) { - currentGame = &gameList[r]; - // consolePrintf("Game list num: %d\n", currentGame); + s_currentGame = &gameList[r]; + // consolePrintf("Game list num: %d\n", s_currentGame); } } } @@ -785,7 +770,7 @@ void checkSleepMode() { } void setShowCursor(bool enable) { - if ((currentGame) && (currentGame->control == CONT_SCUMM_SAMNMAX)) { + if ((s_currentGame) && (s_currentGame->control == CONT_SCUMM_SAMNMAX)) { if (cursorEnable) { sprites[1].attribute[0] = ATTR0_BMP | 150; } else { @@ -801,7 +786,7 @@ void setMouseCursorVisible(bool enable) { mouseCursorVisible = enable; } -void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor, int hotspotX, int hotspotY) { +void setCursorIcon(const u8 *icon, uint w, uint h, byte keycolor, int hotspotX, int hotspotY) { int off; @@ -833,7 +818,7 @@ void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor, int hotspotX, } } - if (currentGame->control != CONT_SCUMM_SAMNMAX) + if (s_currentGame->control != CONT_SCUMM_SAMNMAX) return; uint16 border = RGB15(24,24,24) | 0x8000; @@ -982,7 +967,7 @@ void displayMode16BitFlipBuffer() { consolePrintf("Flip %s...", displayModeIs8Bit ? "8bpp" : "16bpp"); #endif if (!displayModeIs8Bit) { - u16* back = get16BitBackBuffer(); + u16 *back = get16BitBackBuffer(); // highBuffer = !highBuffer; // BG3_CR = BG_BMP16_512x256 | BG_BMP_RAM(highBuffer? 1: 0); @@ -1001,8 +986,8 @@ void displayMode16BitFlipBuffer() { TIMER1_CR = TIMER_ENABLE | TIMER_DIV_1024; u16 t0 = TIMER1_DATA; #endif - const u8* back = (const u8*)get8BitBackBuffer(); - u16* base = BG_GFX + 0x10000; + const u8 *back = (const u8*)get8BitBackBuffer(); + u16 *base = BG_GFX + 0x10000; Rescale_320x256xPAL8_To_256x256x1555( base, back, @@ -1031,17 +1016,18 @@ void displayMode16BitFlipBuffer() { } void setShakePos(int shakePos) { - shakePos = shakePos; + s_shakePos = shakePos; } -u16* get16BitBackBuffer() { +u16 *get16BitBackBuffer() { return BG_GFX + 0x20000; } s32 get8BitBackBufferStride() { - // When the CPU scaler is enabled, the back buffer is in system RAM and is 320 pixels wide - // When the CPU scaler is disabled, the back buffer is in video memory and therefore must have a 512 pixel stride + // When the CPU scaler is enabled, the back buffer is in system RAM and is + // 320 pixels wide. When the CPU scaler is disabled, the back buffer is in + // video memory and therefore must have a 512 pixel stride. if (isCpuScalerEnabled()){ return 320; @@ -1050,11 +1036,11 @@ s32 get8BitBackBufferStride() { } } -u16* getScalerBuffer() { +u16 *getScalerBuffer() { return (u16 *) scalerBackBuffer; } -u16* get8BitBackBuffer() { +u16 *get8BitBackBuffer() { if (isCpuScalerEnabled()) return (u16 *) scalerBackBuffer; else @@ -1124,7 +1110,7 @@ void soundUpdate() { void memoryReport() { int r = 0; - int* p; + int *p; do { p = (int *) malloc(r * 8192); free(p); @@ -1132,7 +1118,7 @@ void memoryReport() { } while ((p) && (r < 512)); int t = -1; - void* block[1024]; + void *block[1024]; do { t++; block[t] = (int *) malloc(4096); @@ -1147,7 +1133,7 @@ void memoryReport() { void addIndyFightingKeys() { - OSystem_DS* system = OSystem_DS::instance(); + OSystem_DS *system = OSystem_DS::instance(); Common::Event event; event.type = Common::EVENT_KEYDOWN; @@ -1247,7 +1233,7 @@ void addIndyFightingKeys() { void setKeyboardEnable(bool en) { if (en == keyboardEnable) return; keyboardEnable = en; - u16* backupBank = (u16 *) 0x6040000; + u16 *backupBank = (u16 *) 0x6040000; if (keyboardEnable) { @@ -1283,7 +1269,7 @@ void setKeyboardEnable(bool en) { if (displayModeIs8Bit) { // Copy the sub screen VRAM from the top screen - they should always be // the same. - u16* buffer = get8BitBackBuffer(); + u16 *buffer = get8BitBackBuffer(); s32 stride = get8BitBackBufferStride(); for (int y = 0; y < gameHeight; y++) { @@ -1319,8 +1305,7 @@ bool getIsDisplayMode8Bit() { return displayModeIs8Bit; } -void doScreenTapMode(OSystem_DS* system) -{ +void doScreenTapMode(OSystem_DS *system) { Common::Event event; static bool left = false, right = false; @@ -1353,7 +1338,7 @@ void doScreenTapMode(OSystem_DS* system) right = true; } - if (!(getKeysHeld() & (KEY_L | KEY_R))) { + if (!isScrollingWithDPad()) { if (getKeysDown() & KEY_LEFT) { event.type = Common::EVENT_LBUTTONDOWN; @@ -1386,21 +1371,17 @@ void doScreenTapMode(OSystem_DS* system) system->addEvent(event); } -void doButtonSelectMode(OSystem_DS* system) -{ +void doButtonSelectMode(OSystem_DS *system) { Common::Event event; - if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { + if (!isScrollingWithDPad()) { event.type = Common::EVENT_MOUSEMOVE; event.mouse = Common::Point(getPenX(), getPenY()); system->addEvent(event); //consolePrintf("x=%d y=%d \n", getPenX(), getPenY()); } - static bool leftButtonDown = false; - static bool rightButtonDown = false; - if (getPenReleased() && (leftButtonDown || rightButtonDown)) { if (leftButtonDown) { event.type = Common::EVENT_LBUTTONUP; @@ -1417,7 +1398,7 @@ void doButtonSelectMode(OSystem_DS* system) if ((mouseMode != MOUSE_HOVER) || (!displayModeIs8Bit)) { - if (getPenDown() && (!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { + if (getPenDown() && !isScrollingWithDPad()) { if (mouseMode == MOUSE_LEFT) { event.type = Common::EVENT_LBUTTONDOWN; leftButtonDown = true; @@ -1459,7 +1440,7 @@ void doButtonSelectMode(OSystem_DS* system) } } - if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (!getIndyFightState()) && (!getKeyboardEnable())) { + if (!isScrollingWithDPad() && !getIndyFightState() && !getKeyboardEnable()) { if (!getPenHeld() || (mouseMode != MOUSE_HOVER)) { if (getKeysDown() & KEY_LEFT) { @@ -1467,7 +1448,6 @@ void doButtonSelectMode(OSystem_DS* system) } if (rightButtonDown) { - Common::Event event; event.mouse = Common::Point(getPenX(), getPenY()); event.type = Common::EVENT_RBUTTONUP; system->addEvent(event); @@ -1476,14 +1456,13 @@ void doButtonSelectMode(OSystem_DS* system) if (getKeysDown() & KEY_RIGHT) { - if ((currentGame->control != CONT_SCUMM_SAMNMAX) && (currentGame->control != CONT_FUTURE_WARS) && (currentGame->control != CONT_GOBLINS)) { + if ((s_currentGame->control != CONT_SCUMM_SAMNMAX) && (s_currentGame->control != CONT_FUTURE_WARS) && (s_currentGame->control != CONT_GOBLINS)) { mouseMode = MOUSE_RIGHT; } else { // If we're playing sam and max, click and release the right mouse // button to change verb - Common::Event event; - if (currentGame->control == CONT_FUTURE_WARS) { + if (s_currentGame->control == CONT_FUTURE_WARS) { event.mouse = Common::Point(320 - 128, 200 - 128); event.type = Common::EVENT_MOUSEMOVE; system->addEvent(event); @@ -1515,7 +1494,7 @@ void addEventsToQueue() { #ifdef HEAVY_LOGGING consolePrintf("addEventsToQueue\n"); #endif - OSystem_DS* system = OSystem_DS::instance(); + OSystem_DS *system = OSystem_DS::instance(); Common::Event event; #ifdef USE_PROFILER @@ -1557,8 +1536,8 @@ void addEventsToQueue() { if (!indyFightState) { - if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R)) && (getKeysDown() & KEY_B)) { - if (currentGame->control == CONT_AGI) { + if (!isScrollingWithDPad() && (getKeysDown() & KEY_B)) { + if (s_currentGame->control == CONT_AGI) { event.kbd.keycode = Common::KEYCODE_RETURN; event.kbd.ascii = 13; event.kbd.flags = 0; @@ -1596,8 +1575,7 @@ void addEventsToQueue() { bool release = getKeysReleased() & (KEY_LEFT | KEY_RIGHT | KEY_UP | KEY_DOWN); bool shoulders = getKeysHeld() & (KEY_L | KEY_R); - if ( (down && (!shoulders)) || release) - { + if ( (down && (!shoulders)) || release) { if (getKeysChanged() & KEY_LEFT) { event.kbd.keycode = Common::KEYCODE_LEFT; @@ -1630,7 +1608,7 @@ void addEventsToQueue() { } - if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (!getIndyFightState()) && (!getKeyboardEnable())) { + if (!isScrollingWithDPad() && !getIndyFightState() && !getKeyboardEnable()) { if ((getKeysDown() & KEY_A) && (!indyFightState)) { gameScreenSwap = !gameScreenSwap; @@ -1669,14 +1647,12 @@ void addEventsToQueue() { } } - if (!getIndyFightState() && !((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (getKeysDown() & KEY_X)) { + if (!getIndyFightState() && !isScrollingWithDPad() && (getKeysDown() & KEY_X)) { setKeyboardEnable(!keyboardEnable); } updateStatus(); - Common::Event event; - if ((tapScreenClicks) && (getIsDisplayMode8Bit())) { if ((!keyboardEnable) || (!isInsideKeyboard(penDownX, penDownY))) { @@ -1693,13 +1669,10 @@ void addEventsToQueue() { if (!keyboardEnable) { - - if (((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R)) || (indyFightState)) && (displayModeIs8Bit)) { + if ((isScrollingWithDPad() || (indyFightState)) && (displayModeIs8Bit)) { // Controls specific to the control method - - - if (currentGame->control == CONT_SKY) { + if (s_currentGame->control == CONT_SKY) { // Extra controls for Beneath a Steel Sky if ((getKeysDown() & KEY_DOWN)) { penY = 0; @@ -1707,9 +1680,8 @@ void addEventsToQueue() { } } - if (currentGame->control == CONT_AGI) { + if (s_currentGame->control == CONT_AGI) { // Extra controls for Leisure Suit Larry and KQ4 - if ((getKeysHeld() & KEY_UP) && (getKeysHeld() & KEY_START) /*&& (!strcmp(gameName, "LLLLL"))*/) { consolePrintf("Cheat key!\n"); @@ -1722,16 +1694,11 @@ void addEventsToQueue() { event.type = Common::EVENT_KEYUP; system->addEvent(event); } - } - - - if (currentGame->control == CONT_SIMON) { + if (s_currentGame->control == CONT_SIMON) { // Extra controls for Simon the Sorcerer if ((getKeysDown() & KEY_DOWN)) { - Common::Event event; - event.type = Common::EVENT_KEYDOWN; event.kbd.keycode = Common::KEYCODE_F10; // F10 or # - show hotspots event.kbd.ascii = Common::ASCII_F10; @@ -1744,13 +1711,9 @@ void addEventsToQueue() { } } - - - if (currentGame->control == CONT_SCUMM_ORIGINAL) { + if (s_currentGame->control == CONT_SCUMM_ORIGINAL) { // Extra controls for Scumm v1-5 games if ((getKeysDown() & KEY_DOWN)) { - Common::Event event; - event.type = Common::EVENT_KEYDOWN; event.kbd.keycode = Common::KEYCODE_PERIOD; // Full stop - skips current dialogue line event.kbd.ascii = '.'; @@ -1806,14 +1769,14 @@ void addEventsToQueue() { if ((getKeysChanged() & KEY_START)) { event.kbd.flags = 0; event.type = getKeyEvent(KEY_START); - if (currentGame->control == CONT_FUTURE_WARS) { + if (s_currentGame->control == CONT_FUTURE_WARS) { event.kbd.keycode = Common::KEYCODE_F10; event.kbd.ascii = Common::ASCII_F10; - } else if (currentGame->control == CONT_GOBLINS) { + } else if (s_currentGame->control == CONT_GOBLINS) { event.kbd.keycode = Common::KEYCODE_F1; event.kbd.ascii = Common::ASCII_F1; // consolePrintf("!!!!!F1!!!!!"); - } else if (currentGame->control == CONT_AGI) { + } else if (s_currentGame->control == CONT_AGI) { event.kbd.keycode = Common::KEYCODE_ESCAPE; event.kbd.ascii = 27; } else { @@ -1830,9 +1793,7 @@ void addEventsToQueue() { } consumeKeys(); - consumePenEvents(); - } } @@ -1862,23 +1823,19 @@ void updateStatus() { if (displayModeIs8Bit) { if (!tapScreenClicks) { switch (mouseMode) { - case MOUSE_LEFT: { - offs = 1; - break; - } - case MOUSE_RIGHT: { - offs = 2; - break; - } - case MOUSE_HOVER: { - offs = 0; - break; - } - default: { - // Nothing! - offs = 0; - break; - } + case MOUSE_LEFT: + offs = 1; + break; + case MOUSE_RIGHT: + offs = 2; + break; + case MOUSE_HOVER: + offs = 0; + break; + default: + // Nothing! + offs = 0; + break; } setIcon(0, 208, 150, offs, 0, true); @@ -1962,15 +1919,12 @@ void setMainScreenScale(int x, int y) { SUB_BG3_YDX = 0; SUB_BG3_YDY = y; } else*/ { - if (isCpuScalerEnabled() && (x==320)) - { + if (isCpuScalerEnabled() && (x==320)) { BG3_XDX = 256; BG3_XDY = 0; BG3_YDX = 0; BG3_YDY = y; - } - else - { + } else { BG3_XDX = x; BG3_XDY = 0; BG3_YDX = 0; @@ -2057,11 +2011,9 @@ void VBlankHandler(void) { soundUpdate(); - - - if ((!gameScreenSwap) && (!(getKeysHeld() & KEY_L) && !(getKeysHeld() & KEY_R))) { - if (currentGame) { - if (currentGame->control != CONT_SCUMM_SAMNMAX) { + if ((!gameScreenSwap) && !isScrollingWithDPad()) { + if (s_currentGame) { + if (s_currentGame->control != CONT_SCUMM_SAMNMAX) { if (getPenHeld() && (getPenY() < SCUMM_GAME_HEIGHT)) { setTopScreenTarget(getPenX(), getPenY()); } @@ -2101,7 +2053,7 @@ void VBlankHandler(void) { callbackTimer -= FRAME_TIME; } - if ((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) { + if (isScrollingWithDPad()) { if ((!dragging) && (getPenHeld()) && (penDownFrames > 5)) { dragging = true; @@ -2144,7 +2096,7 @@ void VBlankHandler(void) { SUB_BG3_CX = subScX + 64; } - SUB_BG3_CY = subScY + (shakePos << 8);*/ + SUB_BG3_CY = subScY + (s_shakePos << 8);*/ /*SUB_BG3_XDX = (int) (subScreenWidth / 256.0f * 256); SUB_BG3_XDY = 0; @@ -2155,7 +2107,7 @@ void VBlankHandler(void) { bool zooming = false; - if ((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) { + if (isScrollingWithDPad()) { if ((getKeysHeld() & KEY_A) && (subScreenScale < ratio)) { subScreenScale += 1; zooming = true; @@ -2232,7 +2184,7 @@ void VBlankHandler(void) { if (displayModeIs8Bit) { - if ((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) { + if (isScrollingWithDPad()) { int offsX = 0, offsY = 0; @@ -2284,7 +2236,7 @@ void VBlankHandler(void) { setZoomedScreenScale(subScreenWidth, ((subScreenHeight * (256 << 8)) / 192) >> 8); - setMainScreenScroll(scX << 8, (scY << 8) + (shakePos << 8)); + setMainScreenScroll(scX << 8, (scY << 8) + (s_shakePos << 8)); setMainScreenScale(256, 256); // 1:1 scale } else { @@ -2300,7 +2252,7 @@ void VBlankHandler(void) { setZoomedScreenScroll(subScX, subScY, (subScreenWidth != 256) && (subScreenWidth != 128)); setZoomedScreenScale(subScreenWidth, ((subScreenHeight * (256 << 8)) / 192) >> 8); - setMainScreenScroll(64, (scY << 8) + (shakePos << 8)); + setMainScreenScroll(64, (scY << 8) + (s_shakePos << 8)); setMainScreenScale(320, 256); // 1:1 scale } @@ -2388,7 +2340,7 @@ void uploadSpriteGfx() { vramSetBankE(VRAM_E_MAIN_SPRITE); // Convert texture from 24bit 888 to 16bit 1555, remembering to set top bit! - u8* srcTex = (u8 *) ::icons_raw; + const u8 *srcTex = (const u8 *) ::icons_raw; for (int r = 32 * 256 ; r >= 0; r--) { SPRITE_GFX_SUB[r] = 0x8000 | (srcTex[r * 3] >> 3) | ((srcTex[r * 3 + 1] >> 3) << 5) | ((srcTex[r * 3 + 2] >> 3) << 10); SPRITE_GFX[r] = 0x8000 | (srcTex[r * 3] >> 3) | ((srcTex[r * 3 + 1] >> 3) << 5) | ((srcTex[r * 3 + 2] >> 3) << 10); @@ -2634,9 +2586,6 @@ void penUpdate() { } } - else - { - } } else { penDown = true; @@ -2822,31 +2771,6 @@ GLvector getPenPos() { return v; } -#ifdef GBA_SRAM_SAVE - -void formatSramOption() { - consolePrintf("The following files are present in save RAM:\n"); - DSSaveFileManager::instance()->listFiles(); - - consolePrintf("\nAre you sure you want to\n"); - consolePrintf("DELETE all files?\n"); - consolePrintf("A = Yes, X = No\n"); - - while (true) { - if (keysHeld() & KEY_A) { - DSSaveFileManager::instance()->formatSram(); - consolePrintf("SRAM cleared!\n"); - return; - } - - if (keysHeld() & KEY_X) { - consolePrintf("Whew, that was close!\n"); - return; - } - } -} -#endif - void setIndyFightState(bool st) { indyFightState = st; indyFightRight = true; @@ -2856,20 +2780,18 @@ bool getIndyFightState() { return indyFightState; } -gameListType* getCurrentGame() { - return currentGame; -} - /////////////////// // Fast Ram /////////////////// #define FAST_RAM_SIZE (24000) -u8* fastRamPointer; +#define ITCM_DATA __attribute__((section(".itcm"))) + +u8 *fastRamPointer; u8 fastRamData[FAST_RAM_SIZE] ITCM_DATA; -void* fastRamAlloc(int size) { - void* result = (void *) fastRamPointer; +void *fastRamAlloc(int size) { + void *result = (void *) fastRamPointer; fastRamPointer += size; if(fastRamPointer > fastRamData + FAST_RAM_SIZE) { consolePrintf("FastRam (ITCM) allocation failed!\n"); @@ -2926,68 +2848,13 @@ void initDebugger() { // Ensure the function is processed with C linkage -extern "C" void debug_print_stub(char* string); +extern "C" void debug_print_stub(char *string); void debug_print_stub(char *string) { consolePrintf(string); } #endif -#ifdef USE_LIBCARTRESET - -struct cardTranslate { - int cartResetId; - int svmId; - char dldiId[5]; -}; - -cardTranslate cardReaderTable[] = { - {DEVICE_TYPE_M3SD, DEVICE_M3SD, "M3SD"}, - {DEVICE_TYPE_M3CF, DEVICE_M3CF, "M3CF"}, - {DEVICE_TYPE_MPCF, DEVICE_MPCF, "MPCF"}, - {DEVICE_TYPE_SCCF, DEVICE_SCCF, "SCCF"}, - {DEVICE_TYPE_SCSD, DEVICE_SCSD, "SCSD"}, - {DEVICE_TYPE_SCSD, DEVICE_SCSD, "SCLT"}, - {DEVICE_TYPE_NMMC, DEVICE_NMMC, "NMMC"}, -}; - -void reboot() { - int deviceType = -1; - - - if (disc_getDeviceId() == DEVICE_DLDI) { - - char id[6]; - disc_getDldiId(id); - - consolePrintf("DLDI Device ID: %s\n", id); - - for (int r = 0; r < ARRAYSIZE(cardReaderTable); r++) { - if (!stricmp(id, cardReaderTable[r].dldiId)) { - deviceType = cardReaderTable[r].cartResetId; - } - } - } else { - for (int r = 0; r < ARRAYSIZE(cardReaderTable); r++) { - if (disc_getDeviceId() == cardReaderTable[r].svmId) { - deviceType = cardReaderTable[r].cartResetId; - } - } - } - - - consolePrintf("Device number: %x\n", deviceType); - - if (deviceType == -1) { - IPC->reset = true; // Send message to ARM7 to turn power off - } else { - cartSetMenuMode(deviceType); - passmeloopEnter(); - } - - while (true); // Stop the program continuing beyond this point -} -#endif void powerOff() { while (keysHeld() != 0) { // Wait for all keys to be released. @@ -3002,12 +2869,10 @@ void powerOff() { while (true); } else { -#ifdef USE_LIBCARTRESET - reboot(); -#else IPC->reset = true; // Send message to ARM7 to turn power off - while (true); // Stop the program continuing beyond this point -#endif + while (true) { + // Stop the program from continuing beyond this point + } } } @@ -3028,7 +2893,7 @@ void dsExceptionHandler() { int offset = 8; - if ( currentMode == 0x17 ) { + if (currentMode == 0x17) { consolePrintf("\x1b[10Cdata abort!\n\n"); codeAddress = exceptionRegisters[15] - offset; if ( (codeAddress > 0x02000000 && codeAddress < 0x02400000) || @@ -3051,16 +2916,19 @@ void dsExceptionHandler() { int i; - for ( i=0; i < 8; i++ ) { + for (i = 0; i < 8; i++) { consolePrintf(" %s: %08X %s: %08X\n", registerNames[i], exceptionRegisters[i], registerNames[i+8],exceptionRegisters[i+8]); } - while(1); + + while(1) + ; // endles loop + u32 *stack = (u32 *)exceptionRegisters[13]; - for ( i=0; i<10; i++ ) { + for (i = 0; i < 10; i++) { consolePrintf("%08X %08X %08X\n", stack[i*3], stack[i*3+1], stack[(i*3)+2] ); } @@ -3286,7 +3154,7 @@ int main(void) { */ // Create a file system node to force search for a zip file in GBA rom space - DSFileSystemNode* node = new DSFileSystemNode(); + DSFileSystemNode *node = new DSFileSystemNode(); if (!node->getZip() || (!node->getZip()->isReady())) { // If not found, init CF/SD driver initGBAMP(mode); @@ -3311,12 +3179,6 @@ int main(void) { g_system = new OSystem_DS(); assert(g_system); -#ifdef GBA_SRAM_SAVE - if ((keysHeld() & KEY_L) && (keysHeld() & KEY_R)) { - formatSramOption(); - } -#endif - IPC->adpcm.semaphore = false; // printf("'%s'", Common::ConfigManager::kTransientDomain.c_str()); @@ -3344,6 +3206,11 @@ int main(void) { const char *argv[] = {"/scummvmds", "--config=scummvmj.ini"}; #elif defined(DS_BUILD_K) const char *argv[] = {"/scummvmds", "--config=scummvmk.ini"}; +#else + // Use the default config file if no build was specified. This currently + // only happens with builds made using the regular ScummVM build system (as + // opposed to the nds specific build system). + const char *argv[] = {"/scummvmds"}; #endif @@ -3356,7 +3223,8 @@ int main(void) { return 0; } -} +} // End of namespace DS + int main() { DS::main(); @@ -3377,7 +3245,6 @@ extern "C" void consolePrintf(char * format, ...) __attribute__ ((no_instrument_ extern "C" void consolePrintf(const char * format, ...) { - char buffer[256]; va_list args; va_start(args, format); viprintf(format, args); diff --git a/backends/platform/ds/arm9/source/dsmain.h b/backends/platform/ds/arm9/source/dsmain.h index beda592ba2..bd627fa620 100644 --- a/backends/platform/ds/arm9/source/dsmain.h +++ b/backends/platform/ds/arm9/source/dsmain.h @@ -8,15 +8,18 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ @@ -25,7 +28,6 @@ #include <nds.h> #include "osystem_ds.h" -#include "NDS/scummvm_ipc.h" namespace DS { @@ -38,7 +40,7 @@ enum controlType { CONT_FUTURE_WARS, CONT_AGI, CONT_GOBLINS, - CONT_NIPPON, + CONT_NIPPON }; struct gameListType { @@ -68,9 +70,6 @@ int leftHandedSwap(int keys); void setGameScreenSwap(bool enable); void setSensitivity(int sensitivity); -// Controls options -void setControls(char* gameName); - // Video void displayMode8Bit(); // Switch to 8-bit mode5 void displayMode16Bit(); // Switch to 16-bit mode5 @@ -79,8 +78,8 @@ void displayMode16Bit(); // Switch to 16-bit mode5 void displayMode16BitFlipBuffer(); // Get address of current back buffer -u16* get16BitBackBuffer(); -u16* get8BitBackBuffer(); +u16 * get16BitBackBuffer(); +u16 * get8BitBackBuffer(); s32 get8BitBackBufferStride(); u16* getScalerBuffer(); @@ -99,7 +98,7 @@ void doTimerCallback(); // Call callback function if required void doSoundCallback(); void startSound(int freq, int buffer); // Start sound hardware // Call function if sound buffers need more data -void playSound(const void* data, u32 length, bool loop, bool adpcm = false, int rate = 22050); // Start a sound +void playSound(const void *data, u32 length, bool loop, bool adpcm = false, int rate = 22050); // Start a sound void stopSound(int channel); int getSoundFrequency(); @@ -109,7 +108,7 @@ void VBlankHandler(); // Sam and Max Stuff void setGameID(int id); -void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor, int hotspotX, int hotspotY); +void setCursorIcon(const u8 *icon, uint w, uint h, byte keycolor, int hotspotX, int hotspotY); void setShowCursor(bool enable); void setMouseCursorVisible(bool visible); @@ -155,10 +154,10 @@ void fastRamReset(); void* fastRamAlloc(int size); void exitGame(); -gameListType* getCurrentGame(); -} +} // End of namespace DS + int cygprofile_getHBlanks(); diff --git a/backends/platform/ds/arm9/source/dsoptions.cpp b/backends/platform/ds/arm9/source/dsoptions.cpp index 9937e81e61..cc89c41017 100644 --- a/backends/platform/ds/arm9/source/dsoptions.cpp +++ b/backends/platform/ds/arm9/source/dsoptions.cpp @@ -8,15 +8,18 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ @@ -31,6 +34,8 @@ #include "touchkeyboard.h" #include "gui/PopUpWidget.h" +#include "common/translation.h" + #define ALLOW_CPU_SCALER namespace DS { @@ -51,27 +56,27 @@ static int confGetInt(Common::String key, int defaultVal) { DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) { - new GUI::ButtonWidget(this, 10, 170, 72, 16, "Close", GUI::kCloseCmd, 'C'); - new GUI::ButtonWidget(this, 320 - 10 - 130, 170, 120, 16, "ScummVM Main Menu", 0x40000000, 'M'); + new GUI::ButtonWidget(this, 10, 170, 72, 16, _("~C~lose"), 0, GUI::kCloseCmd); + new GUI::ButtonWidget(this, 320 - 10 - 130, 170, 120, 16, _("ScummVM Main Menu"), 0, 0x40000000, 'M'); _tab = new GUI::TabWidget(this, 10, 5, 300, 230 - 20 - 40 - 20); _tab->addTab("Controls"); - _leftHandedCheckbox = new GUI::CheckboxWidget(_tab, 5, 5, 130, 20, "Left handed mode", 0, 'L'); - _indyFightCheckbox = new GUI::CheckboxWidget(_tab, 5, 20, 140, 20, "Indy fight controls", 0, 'I'); - _showCursorCheckbox = new GUI::CheckboxWidget(_tab, 150, 5, 130, 20, "Show mouse cursor", 0, 'T'); - _snapToBorderCheckbox = new GUI::CheckboxWidget(_tab, 150, 20, 130, 20, "Snap to edges", 0, 'T'); + _leftHandedCheckbox = new GUI::CheckboxWidget(_tab, 5, 5, 130, 20, _("~L~eft handed mode")); + _indyFightCheckbox = new GUI::CheckboxWidget(_tab, 5, 20, 140, 20, _("~I~ndy fight controls")); + _showCursorCheckbox = new GUI::CheckboxWidget(_tab, 150, 5, 130, 20, _("Show mouse cursor"), 0, 0, 'T'); + _snapToBorderCheckbox = new GUI::CheckboxWidget(_tab, 150, 20, 130, 20, _("Snap to edges"), 0, 0, 'T'); - new GUI::StaticTextWidget(_tab, 20, 35, 100, 15, "Touch X Offset", Graphics::kTextAlignLeft); - _touchX = new GUI::SliderWidget(_tab, 130, 35, 130, 12, 1); + new GUI::StaticTextWidget(_tab, 20, 35, 100, 15, _("Touch X Offset"), Graphics::kTextAlignLeft); + _touchX = new GUI::SliderWidget(_tab, 130, 35, 130, 12, "TODO: Add tooltip", 1); _touchX->setMinValue(-8); _touchX->setMaxValue(+8); _touchX->setValue(0); _touchX->setFlags(GUI::WIDGET_CLEARBG); - new GUI::StaticTextWidget(_tab, 20, 50, 100, 15, "Touch Y Offset", Graphics::kTextAlignLeft); - _touchY = new GUI::SliderWidget(_tab, 130, 50, 130, 12, 2); + new GUI::StaticTextWidget(_tab, 20, 50, 100, 15, _("Touch Y Offset"), Graphics::kTextAlignLeft); + _touchY = new GUI::SliderWidget(_tab, 130, 50, 130, 12, "TODO: Add tooltip", 2); _touchY->setMinValue(-8); _touchY->setMaxValue(+8); _touchY->setValue(0); @@ -82,11 +87,11 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) { new GUI::StaticTextWidget(_tab, 130 - 20, 65, 20, 15, "-8", Graphics::kTextAlignCenter); - _touchPadStyle = new GUI::CheckboxWidget(_tab, 5, 80, 270, 20, "Use laptop trackpad-style cursor control", 0x20000001, 'T'); - _screenTaps = new GUI::CheckboxWidget(_tab, 5, 95, 285, 20, "Tap for left click, double tap right click", 0x20000002, 'T'); + _touchPadStyle = new GUI::CheckboxWidget(_tab, 5, 80, 270, 20, _("Use laptop trackpad-style cursor control"), 0, 0x20000001, 'T'); + _screenTaps = new GUI::CheckboxWidget(_tab, 5, 95, 285, 20, _("Tap for left click, double tap right click"), 0, 0x20000002, 'T'); - _sensitivityLabel = new GUI::StaticTextWidget(_tab, 20, 110, 110, 15, "Sensitivity", Graphics::kTextAlignLeft); - _sensitivity = new GUI::SliderWidget(_tab, 130, 110, 130, 12, 1); + _sensitivityLabel = new GUI::StaticTextWidget(_tab, 20, 110, 110, 15, _("Sensitivity"), Graphics::kTextAlignLeft); + _sensitivity = new GUI::SliderWidget(_tab, 130, 110, 130, 12, "TODO: Add tooltip", 1); _sensitivity->setMinValue(4); _sensitivity->setMaxValue(16); _sensitivity->setValue(8); @@ -94,20 +99,20 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) { _tab->addTab("Graphics"); - new GUI::StaticTextWidget(_tab, 5, 67, 180, 15, "Initial top screen scale:", Graphics::kTextAlignLeft); + new GUI::StaticTextWidget(_tab, 5, 67, 180, 15, _("Initial top screen scale:"), Graphics::kTextAlignLeft); - _100PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 82, 80, 20, "100%", 0x30000001, 'T'); - _150PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 97, 80, 20, "150%", 0x30000002, 'T'); - _200PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 112, 80, 20, "200%", 0x30000003, 'T'); + _100PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 82, 80, 20, "100%", "TODO: Add tooltip", 0x30000001, 'T'); + _150PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 97, 80, 20, "150%", "TODO: Add tooltip", 0x30000002, 'T'); + _200PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 112, 80, 20, "200%", "TODO: Add tooltip", 0x30000003, 'T'); - new GUI::StaticTextWidget(_tab, 5, 5, 180, 15, "Main screen scaling:", Graphics::kTextAlignLeft); + new GUI::StaticTextWidget(_tab, 5, 5, 180, 15, _("Main screen scaling:"), Graphics::kTextAlignLeft); - _hardScaler = new GUI::CheckboxWidget(_tab, 5, 20, 270, 20, "Hardware scale (fast, but low quality)", 0x10000001, 'T'); - _cpuScaler = new GUI::CheckboxWidget(_tab, 5, 35, 270, 20, "Software scale (good quality, but slower)", 0x10000002, 'S'); - _unscaledCheckbox = new GUI::CheckboxWidget(_tab, 5, 50, 270, 20, "Unscaled (you must scroll left and right)", 0x10000003, 'S'); + _hardScaler = new GUI::CheckboxWidget(_tab, 5, 20, 270, 20, _("Hardware scale (fast, but low quality)"), 0, 0x10000001, 'T'); + _cpuScaler = new GUI::CheckboxWidget(_tab, 5, 35, 270, 20, _("Software scale (good quality, but slower)"), 0, 0x10000002, 'S'); + _unscaledCheckbox = new GUI::CheckboxWidget(_tab, 5, 50, 270, 20, _("Unscaled (you must scroll left and right)"), 0, 0x10000003, 'S'); - new GUI::StaticTextWidget(_tab, 5, 125, 110, 15, "Brightness:", Graphics::kTextAlignLeft); - _gammaCorrection = new GUI::SliderWidget(_tab, 130, 120, 130, 12, 1); + new GUI::StaticTextWidget(_tab, 5, 125, 110, 15, _("Brightness:"), Graphics::kTextAlignLeft); + _gammaCorrection = new GUI::SliderWidget(_tab, 130, 120, 130, 12, "TODO: Add tooltip", 1); _gammaCorrection->setMinValue(0); _gammaCorrection->setMaxValue(8); _gammaCorrection->setValue(0); @@ -116,8 +121,8 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) { _tab->addTab("General"); - _highQualityAudioCheckbox = new GUI::CheckboxWidget(_tab, 5, 5, 250, 20, "High quality audio (slower) (reboot)", 0, 'T'); - _disablePowerOff = new GUI::CheckboxWidget(_tab, 5, 20, 200, 20, "Disable power off", 0, 'T'); + _highQualityAudioCheckbox = new GUI::CheckboxWidget(_tab, 5, 5, 250, 20, _("High quality audio (slower) (reboot)"), 0, 0, 'T'); + _disablePowerOff = new GUI::CheckboxWidget(_tab, 5, 20, 200, 20, _("Disable power off"), 0, 0, 'T'); _tab->setActiveTab(0); @@ -125,7 +130,7 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) { #ifdef DS_SCUMM_BUILD if (!DS::isGBAMPAvailable()) { -// addButton(this, 100, 140, "Delete Save", 'dels', 'D'); +// addButton(this, 100, 140, "Delete Save", 0, 'dels', 'D'); } #endif @@ -133,7 +138,7 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) { //#ifdef ALLOW_CPU_SCALER -// _cpuScaler = new GUI::CheckboxWidget(this, 160, 115, 90, 20, "CPU scaler", 0, 'T'); +// _cpuScaler = new GUI::CheckboxWidget(this, 160, 115, 90, 20, "CPU scaler", 0, 0, 'T'); //#endif @@ -364,7 +369,7 @@ void showOptionsDialog() { DS::displayMode16Bit(); - DSOptionsDialog* d = new DSOptionsDialog(); + DSOptionsDialog *d = new DSOptionsDialog(); d->runModal(); delete d; @@ -418,7 +423,7 @@ void setOptions() { DS::setTrackPadStyleEnable(enable); - if ((enable) and (firstLoad)) { + if (enable && firstLoad) { // If we've just booted up, want to swap screens when trackpad mode is in use // but not every time we enter the options dialog. DS::setGameScreenSwap(true); @@ -436,4 +441,5 @@ void setOptions() { firstLoad = false; } -} +} // End of namespace DS + diff --git a/backends/platform/ds/arm9/source/dsoptions.h b/backends/platform/ds/arm9/source/dsoptions.h index 4b3ac36d45..1bdc7c1f27 100644 --- a/backends/platform/ds/arm9/source/dsoptions.h +++ b/backends/platform/ds/arm9/source/dsoptions.h @@ -8,15 +8,18 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ @@ -46,30 +49,30 @@ protected: virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data); void updateConfigManager(); - GUI::TabWidget* _tab; + GUI::TabWidget *_tab; - GUI::StaticTextWidget* _sensitivityLabel; + GUI::StaticTextWidget *_sensitivityLabel; - GUI::SliderWidget* _touchX; - GUI::SliderWidget* _touchY; - GUI::SliderWidget* _sensitivity; - GUI::SliderWidget* _gammaCorrection; - GUI::CheckboxWidget* _leftHandedCheckbox; - GUI::CheckboxWidget* _unscaledCheckbox; - GUI::CheckboxWidget* _100PercentCheckbox; - GUI::CheckboxWidget* _150PercentCheckbox; - GUI::CheckboxWidget* _200PercentCheckbox; - GUI::CheckboxWidget* _indyFightCheckbox; - GUI::CheckboxWidget* _highQualityAudioCheckbox; - GUI::CheckboxWidget* _disablePowerOff; - GUI::CheckboxWidget* _showCursorCheckbox; - GUI::CheckboxWidget* _snapToBorderCheckbox; + GUI::SliderWidget *_touchX; + GUI::SliderWidget *_touchY; + GUI::SliderWidget *_sensitivity; + GUI::SliderWidget *_gammaCorrection; + GUI::CheckboxWidget *_leftHandedCheckbox; + GUI::CheckboxWidget *_unscaledCheckbox; + GUI::CheckboxWidget *_100PercentCheckbox; + GUI::CheckboxWidget *_150PercentCheckbox; + GUI::CheckboxWidget *_200PercentCheckbox; + GUI::CheckboxWidget *_indyFightCheckbox; + GUI::CheckboxWidget *_highQualityAudioCheckbox; + GUI::CheckboxWidget *_disablePowerOff; + GUI::CheckboxWidget *_showCursorCheckbox; + GUI::CheckboxWidget *_snapToBorderCheckbox; - GUI::CheckboxWidget* _hardScaler; - GUI::CheckboxWidget* _cpuScaler; + GUI::CheckboxWidget *_hardScaler; + GUI::CheckboxWidget *_cpuScaler; - GUI::CheckboxWidget* _touchPadStyle; - GUI::CheckboxWidget* _screenTaps; + GUI::CheckboxWidget *_touchPadStyle; + GUI::CheckboxWidget *_screenTaps; bool _radioButtonMode; @@ -78,6 +81,6 @@ protected: extern void showOptionsDialog(); extern void setOptions(); -} +} // End of namespace DS #endif diff --git a/backends/platform/ds/arm9/source/fat/gba_nds_fat.c b/backends/platform/ds/arm9/source/fat/gba_nds_fat.c index b70d9e7b99..07affd8839 100644 --- a/backends/platform/ds/arm9/source/fat/gba_nds_fat.c +++ b/backends/platform/ds/arm9/source/fat/gba_nds_fat.c @@ -294,9 +294,9 @@ u16 getRTCtoFileTime (void) { #ifdef NDS return ( - ( ( (IPC->rtc_hours > 11 ? IPC->rtc_hours - 40 : IPC->rtc_hours) & 0x1F) << 11) | - ( (IPC->rtc_minutes & 0x3F) << 5) | - ( (IPC->rtc_seconds >> 1) & 0x1F) ); + ( ( (IPC->rtc.hours > 11 ? IPC->rtc.hours - 40 : IPC->rtc.hours) & 0x1F) << 11) | + ( (IPC->rtc.minutes & 0x3F) << 5) | + ( (IPC->rtc.seconds >> 1) & 0x1F) ); #else return 0; #endif @@ -306,9 +306,9 @@ u16 getRTCtoFileDate (void) { #ifdef NDS return ( - ( ((IPC->rtc_year + 20) & 0x7F) <<9) | - ( (IPC->rtc_month & 0xF) << 5) | - (IPC->rtc_day & 0x1F) ); + ( ((IPC->rtc.year + 20) & 0x7F) <<9) | + ( (IPC->rtc.month & 0xF) << 5) | + (IPC->rtc.day & 0x1F) ); #else return 0; #endif diff --git a/backends/platform/ds/arm9/source/fat/io_nmmc.c b/backends/platform/ds/arm9/source/fat/io_nmmc.c index 261096a27b..6c996f5de1 100644 --- a/backends/platform/ds/arm9/source/fat/io_nmmc.c +++ b/backends/platform/ds/arm9/source/fat/io_nmmc.c @@ -170,7 +170,7 @@ bool NMMC_IsInserted(void) { Neo_EnableMMC( true ); // Open SPI port to MMC card Neo_SendMMCCommand(MMC_SEND_CSD, 0); - if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured + if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occurred Neo_EnableMMC( false ); return false; } @@ -227,14 +227,14 @@ bool NMMC_StartUp(void) { // Set block length Neo_SendMMCCommand(MMC_SET_BLOCKLEN, BYTE_PER_READ ); - if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured + if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occurred Neo_EnableMMC( false ); return false; } // Check if we can use a higher SPI frequency Neo_SendMMCCommand(MMC_SEND_CSD, 0); - if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured + if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occurred Neo_EnableMMC( false ); return false; } @@ -268,7 +268,7 @@ bool NMMC_WriteSectors (u32 sector, u8 numSecs, void* buffer) Neo_EnableMMC( true ); // Open SPI port to MMC card Neo_SendMMCCommand( 25, sector ); - if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured + if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occurred Neo_EnableMMC( false ); return false; } @@ -318,7 +318,7 @@ bool NMMC_ReadSectors (u32 sector, u8 numSecs, void* buffer) while (totalSecs--) { Neo_SendMMCCommand(MMC_READ_BLOCK, sector ); - if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured + if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occurred Neo_EnableMMC( false ); return false; } diff --git a/backends/platform/ds/arm9/source/gbampsave.cpp b/backends/platform/ds/arm9/source/gbampsave.cpp index 820e569555..d0fb8fff3b 100644 --- a/backends/platform/ds/arm9/source/gbampsave.cpp +++ b/backends/platform/ds/arm9/source/gbampsave.cpp @@ -8,15 +8,18 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ @@ -29,7 +32,7 @@ // GBAMP Save File ///////////////////////// -GBAMPSaveFile::GBAMPSaveFile(char* name, bool saveOrLoad) { +GBAMPSaveFile::GBAMPSaveFile(char *name, bool saveOrLoad) { handle = DS::std_fopen(name, saveOrLoad? "w": "r"); // consolePrintf("%s handle is %d\n", name, handle); // consolePrintf("Created %s\n", name); @@ -44,10 +47,10 @@ GBAMPSaveFile::~GBAMPSaveFile() { // consolePrintf("Closed file\n"); } -uint32 GBAMPSaveFile::read(void *buf, uint32 size) { - saveSize += size; -// consolePrintf("Read %d %d ", size, saveSize); - return DS::std_fread(buf, 1, size, handle); +uint32 GBAMPSaveFile::read(void *buf, uint32 length) { + saveSize += length; +// consolePrintf("Read %d %d ", length, saveSize); + return DS::std_fread(buf, 1, length, handle); } bool GBAMPSaveFile::eos() const { @@ -74,27 +77,27 @@ int32 GBAMPSaveFile::pos() const { int32 GBAMPSaveFile::size() const { int position = pos(); DS::std_fseek(handle, 0, SEEK_END); - int size = DS::std_ftell(handle); + int length = DS::std_ftell(handle); DS::std_fseek(handle, position, SEEK_SET); - return size; + return length; } -bool GBAMPSaveFile::seek(int32 pos, int whence) { - return DS::std_fseek(handle, pos, whence) == 0; +bool GBAMPSaveFile::seek(int32 newPos, int whence) { + return DS::std_fseek(handle, newPos, whence) == 0; } -uint32 GBAMPSaveFile::write(const void *buf, uint32 size) { - if (bufferPos + size > SAVE_BUFFER_SIZE) { +uint32 GBAMPSaveFile::write(const void *buf, uint32 length) { + if (bufferPos + length > SAVE_BUFFER_SIZE) { flushSaveBuffer(); - saveSize += size; -// consolePrintf("Writing %d bytes from %x", size, buf); -// DS::std_fwrite(buf, 1, size, handle); + saveSize += length; +// consolePrintf("Writing %d bytes from %x", length, buf); +// DS::std_fwrite(buf, 1, length, handle); - memcpy(buffer + bufferPos, buf, size); - bufferPos += size; + memcpy(buffer + bufferPos, buf, length); + bufferPos += length; - saveSize += size; + saveSize += length; /* int pos = 0; @@ -104,31 +107,31 @@ uint32 GBAMPSaveFile::write(const void *buf, uint32 size) { bufferPos = 512; pos += rest; flushSaveBuffer(); - size -= rest; + length -= rest; // consolePrintf("First section: %d\n", rest); - while (size >= 512) { + while (length >= 512) { DS::std_fwrite(((char *) (buf)) + pos, 1, 512, handle); - size -= 512; + length -= 512; pos += 512; -// consolePrintf("Full chunk, %d left ", size); +// consolePrintf("Full chunk, %d left ", length); } bufferPos = 0; - memcpy(buffer + bufferPos, ((char *) (buf)) + pos, size); - bufferPos += size; + memcpy(buffer + bufferPos, ((char *) (buf)) + pos, length); + bufferPos += length; // consolePrintf("%d left in buffer ", bufferPos);*/ } else { - memcpy(buffer + bufferPos, buf, size); - bufferPos += size; + memcpy(buffer + bufferPos, buf, length); + bufferPos += length; - saveSize += size; + saveSize += length; } -// if ((size > 100) || (size <= 0)) consolePrintf("Write %d bytes\n", size); - return size; +// if ((length > 100) || (length <= 0)) consolePrintf("Write %d bytes\n", length); + return length; } @@ -196,7 +199,7 @@ Common::StringArray GBAMPSaveFileManager::listSavefiles(const Common::String &pa // consolePrintf("Real cwd:%d\n", realName); - char* p = realName; + char *p = realName; while (*p) { if (*p == '\\') *p = '/'; p++; diff --git a/backends/platform/ds/arm9/source/gbampsave.h b/backends/platform/ds/arm9/source/gbampsave.h index bc4fdaa1a4..ad929236cd 100644 --- a/backends/platform/ds/arm9/source/gbampsave.h +++ b/backends/platform/ds/arm9/source/gbampsave.h @@ -8,15 +8,18 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ @@ -24,19 +27,20 @@ #define _GBAMPSAVE_H_ #include "common/system.h" +#include "common/savefile.h" #include "backends/fs/ds/ds-fs.h" #define SAVE_BUFFER_SIZE 100000 class GBAMPSaveFile : public Common::InSaveFile, public Common::OutSaveFile { - DS::fileHandle* handle; + DS::fileHandle *handle; char buffer[SAVE_BUFFER_SIZE]; int bufferPos; int saveSize; int flushed; public: - GBAMPSaveFile(char* name, bool saveOrLoad); + GBAMPSaveFile(char *name, bool saveOrLoad); virtual ~GBAMPSaveFile(); virtual uint32 read(void *buf, uint32 size); @@ -62,12 +66,12 @@ public: GBAMPSaveFileManager(); ~GBAMPSaveFileManager(); -// static GBAMPSaveFileManager* instance() { return instancePtr; } +// static GBAMPSaveFileManager *instance() { return instancePtr; } GBAMPSaveFile *openSavefile(const char *filename, bool saveOrLoad); - virtual Common::OutSaveFile* openForSaving(const Common::String &filename) { return openSavefile(filename.c_str(), true); } - virtual Common::InSaveFile* openForLoading(const Common::String &filename) { return openSavefile(filename.c_str(), false); } + virtual Common::OutSaveFile *openForSaving(const Common::String &filename) { return openSavefile(filename.c_str(), true); } + virtual Common::InSaveFile *openForLoading(const Common::String &filename) { return openSavefile(filename.c_str(), false); } virtual bool removeSavefile(const Common::String &filename) { return false; } // TODO: Implement this virtual Common::StringArray listSavefiles(const Common::String &pattern); diff --git a/backends/platform/ds/arm9/source/keys.cpp b/backends/platform/ds/arm9/source/keys.cpp index 63fae866e5..2f8497ab19 100644 --- a/backends/platform/ds/arm9/source/keys.cpp +++ b/backends/platform/ds/arm9/source/keys.cpp @@ -74,7 +74,6 @@ #include <nds/system.h> #include <nds/arm9/input.h> -//------------------------------------------------------------------------------ #define KEYS_CUR (( ((~REG_KEYINPUT)&0x3ff) | (((~IPC->buttons)&3)<<10) | (((~IPC->buttons)<<6) & (KEY_TOUCH|KEY_LID) ))^KEY_LID) @@ -89,63 +88,50 @@ static u8 delay = 60, repeat = 30, count = 60; static uint16 oldx = 0; static uint16 oldy = 0; -//------------------------------------------------------------------------------ void scanKeys(void) { -//------------------------------------------------------------------------------ keysold = keys; keys = KEYS_CUR; oldx = IPC->touchXpx; oldy = IPC->touchYpx; - if ( delay != 0 ) { - if ( keys != keysold ) { - count = delay ; - keysrepeat = keysDown() ; + if (delay != 0) { + if (keys != keysold) { + count = delay; + keysrepeat = keysDown(); } count--; - if ( count == 0 ) { + if (count == 0) { count = repeat; keysrepeat = keys; } } } -//------------------------------------------------------------------------------ uint32 keysHeld(void) { -//------------------------------------------------------------------------------ return keys; } -//------------------------------------------------------------------------------ uint32 keysDown(void) { -//------------------------------------------------------------------------------ return (keys ^ keysold) & keys; } -//------------------------------------------------------------------------------ uint32 keysDownRepeat(void) { -//------------------------------------------------------------------------------ uint32 tmp = keysrepeat; - keysrepeat = 0; - return tmp; } -//------------------------------------------------------------------------------ void keysSetRepeat( u8 setDelay, u8 setRepeat ) { -//------------------------------------------------------------------------------ - delay = setDelay ; - repeat = setRepeat ; - count = delay ; - keysrepeat = 0 ; + delay = setDelay; + repeat = setRepeat; + count = delay; + keysrepeat = 0; } -//------------------------------------------------------------------------------ uint32 keysUp(void) { -//------------------------------------------------------------------------------ return (keys ^ keysold) & (~keys); } -} // namespace ds +} // End of namespace DS + diff --git a/backends/platform/ds/arm9/source/keys.h b/backends/platform/ds/arm9/source/keys.h index e0f28a12cf..8d08014232 100644 --- a/backends/platform/ds/arm9/source/keys.h +++ b/backends/platform/ds/arm9/source/keys.h @@ -1,4 +1,27 @@ +/* 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$ + * + */ namespace DS { @@ -7,7 +30,7 @@ void scanKeys(void); uint32 keysHeld(void); uint32 keysDown(void); uint32 keysDownRepeat(void); -void keysSetRepeat( u8 setDelay, u8 setRepeat ); +void keysSetRepeat(u8 setDelay, u8 setRepeat); uint32 keysUp(void); -} +} // End of namespace DS diff --git a/backends/platform/ds/arm9/source/libcartreset/cartreset.c b/backends/platform/ds/arm9/source/libcartreset/cartreset.c deleted file mode 100644 index 6fb906b86d..0000000000 --- a/backends/platform/ds/arm9/source/libcartreset/cartreset.c +++ /dev/null @@ -1,107 +0,0 @@ -/********************************** - Copyright (C) Rick Wong (Lick) - http://licklick.wordpress.com/ -***********************************/ -#include <cartreset_nolibfat.h> - - -#ifdef ARM9 - -bool cartSetMenuMode(u32 _deviceType) -{ - *(vu16*)(0x04000204) &= ~0x0880; //sysSetBusOwners(true, true); - u32 deviceType = _deviceType; - - *((vu32*)0x027FFFF8) = 0x080000C0; // ARM7 reset address - - if(deviceType == DEVICE_TYPE_EFA2) - { - *(u16 *)0x9FE0000 = 0xD200; - *(u16 *)0x8000000 = 0x1500; - *(u16 *)0x8020000 = 0xD200; - *(u16 *)0x8040000 = 0x1500; - *(u16 *)0x9880000 = 1 << 15; - *(u16 *)0x9FC0000 = 0x1500; - return true; - } - else if(deviceType == DEVICE_TYPE_MPCF) - { - return true; - } - else if(deviceType == DEVICE_TYPE_EZSD) - { - return true; - } - else if(deviceType == DEVICE_TYPE_M3CF || deviceType == DEVICE_TYPE_M3SD) - { - u32 mode = 0x00400004; - vu16 tmp; - tmp = *(vu16*)(0x08E00002); - tmp = *(vu16*)(0x0800000E); - tmp = *(vu16*)(0x08801FFC); - tmp = *(vu16*)(0x0800104A); - tmp = *(vu16*)(0x08800612); - tmp = *(vu16*)(0x08000000); - tmp = *(vu16*)(0x08801B66); - tmp = *(vu16*)(0x08000000 + (mode << 1)); - tmp = *(vu16*)(0x0800080E); - tmp = *(vu16*)(0x08000000); - - tmp = *(vu16*)(0x080001E4); - tmp = *(vu16*)(0x080001E4); - tmp = *(vu16*)(0x08000188); - tmp = *(vu16*)(0x08000188); - return true; - } - else if(deviceType == DEVICE_TYPE_SCCF || deviceType == DEVICE_TYPE_SCSD) - { - *(vu16*)0x09FFFFFE = 0xA55A; - *(vu16*)0x09FFFFFE = 0xA55A; - *(vu16*)0x09FFFFFE = 0; - *(vu16*)0x09FFFFFE = 0; - *((vu32*)0x027FFFF8) = 0x08000000; // Special ARM7 reset address - return true; - } - - return false; -} - - - -void passmeloopEnter() -{ - *(vu16*)(0x04000208) = 0; //REG_IME = IME_DISABLE; - *(vu16*)(0x04000204) |= 0x0880; //sysSetBusOwners(false, false); - *((vu32*)0x027FFFFC) = 0; - *((vu32*)0x027FFE04) = (u32)0xE59FF018; - *((vu32*)0x027FFE24) = (u32)0x027FFE04; - asm("swi 0x00"); //swiSoftReset(); - asm("bx lr"); -} - -#endif - - -#ifdef ARM7 - -bool passmeloopQuery() -{ - if(*((vu32*)0x027FFE24) == (u32)0x027FFE04) - return true; - return false; -} - - - -void cartExecute() -{ - *(vu16*)(0x04000208) = 0; //REG_IME = IME_DISABLE; - *((vu32*)0x027FFE34) = *((vu32*)0x027FFFF8); - asm("swi 0x00"); //swiSoftReset(); - asm("bx lr"); -} - -#endif - - - diff --git a/backends/platform/ds/arm9/source/libcartreset/cartreset_nolibfat.h b/backends/platform/ds/arm9/source/libcartreset/cartreset_nolibfat.h deleted file mode 100644 index ddc4b1d4c2..0000000000 --- a/backends/platform/ds/arm9/source/libcartreset/cartreset_nolibfat.h +++ /dev/null @@ -1,57 +0,0 @@ -/********************************** - Copyright (C) Rick Wong (Lick) - http://licklick.wordpress.com/ -***********************************/ -#ifndef CARTRESET_H -#define CARTRESET_H - -//#include <fat.h> -#include <nds.h> - - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef ARM9 -// Auto detect: -#define DEVICE_TYPE_AUTO 0x00000000 // doesn't work in libcartreset "nolibfat" version - -// Not supported: -#define DEVICE_TYPE_FCSR 0x52534346 -#define DEVICE_TYPE_MMCF 0x46434D4D -#define DEVICE_TYPE_NJSD 0x44534A4E -#define DEVICE_TYPE_NMMC 0x434D4D4E - -// Supported: -#define DEVICE_TYPE_EFA2 0x32414645 -#define DEVICE_TYPE_MPCF 0x4643504D -#define DEVICE_TYPE_M3CF 0x4643334D -#define DEVICE_TYPE_M3SD 0x4453334D -#define DEVICE_TYPE_SCCF 0x46434353 -#define DEVICE_TYPE_SCSD 0x44534353 - -// Supported, but libfat doesn't detect the device: -#define DEVICE_TYPE_EZSD 0x44535A45 - - -bool cartSetMenuMode(u32 _deviceType); -void passmeloopEnter(); - -#endif - - -#ifdef ARM7 - -bool passmeloopQuery(); -void cartExecute(); - -#endif - - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp index 691fb2ec7a..c4ff241de0 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.cpp +++ b/backends/platform/ds/arm9/source/osystem_ds.cpp @@ -66,9 +66,14 @@ #define DEFAULT_CONFIG_FILE "scummvmj.ini" #elif defined(DS_BUILD_K) #define DEFAULT_CONFIG_FILE "scummvmk.ini" +#else + // Use the "scummvm.ini" as config file if no build was specified. This + // currently only happens with builds made using the regular ScummVM build + // system (as opposed to the nds specific build system). +#define DEFAULT_CONFIG_FILE "scummvm.ini" #endif -OSystem_DS* OSystem_DS::_instance = NULL; +OSystem_DS *OSystem_DS::_instance = NULL; OSystem_DS::OSystem_DS() : eventNum(0), lastPenFrame(0), queuePos(0), _mixer(NULL), _timer(NULL), _frameBufferExists(false), @@ -128,7 +133,7 @@ bool OSystem_DS::getFeatureState(Feature f) { return false; } -const OSystem::GraphicsMode* OSystem_DS::getSupportedGraphicsModes() const { +const OSystem::GraphicsMode *OSystem_DS::getSupportedGraphicsModes() const { return s_supportedGraphicsModes; } @@ -203,8 +208,7 @@ void OSystem_DS::setPalette(const byte *colors, uint start, uint num) { } } -void OSystem_DS::restoreHardwarePalette() -{ +void OSystem_DS::restoreHardwarePalette() { // Set the hardware palette up based on the stored palette for (int r = 0; r < 255; r++) { @@ -238,13 +242,13 @@ void OSystem_DS::setCursorPalette(const byte *colors, uint start, uint num) { refreshCursor(); } -bool OSystem_DS::grabRawScreen(Graphics::Surface* surf) { +bool OSystem_DS::grabRawScreen(Graphics::Surface *surf) { surf->create(DS::getGameWidth(), DS::getGameHeight(), 1); // Ensure we copy using 16 bit quantities due to limitation of VRAM addressing - const u16* image = (const u16 *) DS::get8BitBackBuffer(); + const u16 *image = (const u16 *) DS::get8BitBackBuffer(); for (int y = 0; y < DS::getGameHeight(); y++) { DC_FlushRange(image + (y << 8), DS::getGameWidth()); for (int x = 0; x < DS::getGameWidth() >> 1; x++) { @@ -277,9 +281,9 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int // consolePrintf("CopyRectToScreen %d\n", w * h); - u16* bg; + u16 *bg; s32 stride; - u16* bgSub = (u16 *)BG_GFX_SUB; + u16 *bgSub = (u16 *)BG_GFX_SUB; // The DS video RAM doesn't support 8-bit writes because Nintendo wanted // to save a few pennies/euro cents on the hardware. @@ -304,14 +308,14 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int // the keyboard image uses the same VRAM addresses. for (int dy = y; dy < y + h; dy++) { - u8* dest = ((u8 *) (bg)) + (dy * stride) + x; - u8* src = (u8 *) buf + (pitch * by); + u8 *dest = ((u8 *) (bg)) + (dy * stride) + x; + const u8 *src = (const u8 *) buf + (pitch * by); u32 dx; u32 pixelsLeft = w; - if (MISALIGNED16(dest)) { + if (MISALIGNED16(dest)) { // Read modify write dest--; @@ -326,9 +330,9 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int } // We can now assume dest is aligned - u16* dest16 = (u16 *) dest; + u16 *dest16 = (u16 *) dest; - for (dx = 0; dx < pixelsLeft; dx+=2) { + for (dx = 0; dx < pixelsLeft; dx+=2) { u16 mix; mix = *src + (*(src + 1) << 8); @@ -355,15 +359,15 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int // When they keyboard is not on screen, update both vram copies for (int dy = y; dy < y + h; dy++) { - u8* dest = ((u8 *) (bg)) + (dy * stride) + x; - u8* destSub = ((u8 *) (bgSub)) + (dy * 512) + x; - u8* src = (u8 *) buf + (pitch * by); + u8 *dest = ((u8 *) (bg)) + (dy * stride) + x; + u8 *destSub = ((u8 *) (bgSub)) + (dy * 512) + x; + const u8 *src = (const u8 *) buf + (pitch * by); u32 dx; u32 pixelsLeft = w; - if (MISALIGNED16(dest)) { + if (MISALIGNED16(dest)) { // Read modify write dest--; @@ -380,10 +384,10 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int } // We can now assume dest is aligned - u16* dest16 = (u16 *) dest; - u16* destSub16 = (u16 *) destSub; + u16 *dest16 = (u16 *) dest; + u16 *destSub16 = (u16 *) destSub; - for (dx = 0; dx < pixelsLeft; dx+=2) { + for (dx = 0; dx < pixelsLeft; dx+=2) { u16 mix; mix = *src + (*(src + 1) << 8); @@ -417,12 +421,12 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int // Stuff is aligned to 16-bit boundaries, so it's safe to do DMA. - u16* src = (u16 *) buf; + u16 *src = (u16 *) buf; if (DS::getKeyboardEnable()) { for (int dy = y; dy < y + h; dy++) { - u16* dest = bg + (dy * (stride >> 1)) + (x >> 1); + u16 *dest = bg + (dy * (stride >> 1)) + (x >> 1); DC_FlushRange(src, w << 1); DC_FlushRange(dest, w << 1); @@ -435,8 +439,8 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int } else { for (int dy = y; dy < y + h; dy++) { - u16* dest1 = bg + (dy * (stride >> 1)) + (x >> 1); - u16* dest2 = bgSub + (dy << 8) + (x >> 1); + u16 *dest1 = bg + (dy * (stride >> 1)) + (x >> 1); + u16 *dest2 = bgSub + (dy << 8) + (x >> 1); DC_FlushRange(src, w << 1); DC_FlushRange(dest1, w << 1); @@ -458,7 +462,7 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int } void OSystem_DS::updateScreen() { - static int cnt = 0; +// static int cnt = 0; // consolePrintf("updatescr %d\n", cnt++); if ((_frameBufferExists) && (DS::getIsDisplayMode8Bit())) { @@ -498,13 +502,13 @@ void OSystem_DS::clearOverlay() { // consolePrintf("clearovl\n"); } -void OSystem_DS::grabOverlay(OverlayColor* buf, int pitch) { +void OSystem_DS::grabOverlay(OverlayColor *buf, int pitch) { // consolePrintf("grabovl\n") - u16* start = DS::get16BitBackBuffer(); + u16 *start = DS::get16BitBackBuffer(); for (int y = 0; y < 200; y++) { - u16* src = start + (y * 320); - u16* dest = ((u16 *) (buf)) + (y * pitch); + u16 *src = start + (y * 320); + u16 *dest = ((u16 *) (buf)) + (y * pitch); for (int x = 0; x < 320; x++) { *dest++ = *src++; @@ -514,8 +518,8 @@ void OSystem_DS::grabOverlay(OverlayColor* buf, int pitch) { } void OSystem_DS::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) { - u16* bg = (u16 *) DS::get16BitBackBuffer(); - const u16* src = (const u16 *) buf; + u16 *bg = (u16 *) DS::get16BitBackBuffer(); + const u16 *src = (const u16 *) buf; // if (x + w > 256) w = 256 - x; //if (x + h > 256) h = 256 - y; @@ -586,7 +590,7 @@ void OSystem_DS::refreshCursor() { DS::setCursorIcon(_cursorImage, _cursorW, _cursorH, _cursorKey, _cursorHotX, _cursorHotY); } -void OSystem_DS::addEvent(Common::Event& e) { +void OSystem_DS::addEvent(const Common::Event& e) { eventQueue[queuePos++] = e; } @@ -724,31 +728,15 @@ void OSystem_DS::quit() { swiSoftReset();*/ } -Common::SaveFileManager* OSystem_DS::getSavefileManager() { - bool forceSram; - - if (ConfMan.hasKey("forcesramsave", "ds")) { - forceSram = ConfMan.getBool("forcesramsave", "ds"); - } else { - forceSram = false; - } - if (forceSram) { - consolePrintf("Using SRAM save method!\n"); - } - - if (DS::isGBAMPAvailable() && (!forceSram)) { +Common::SaveFileManager *OSystem_DS::getSavefileManager() { + if (DS::isGBAMPAvailable()) { return &mpSaveManager; - } else { -#ifdef GBA_SRAM_SAVE - return &saveManager; -#else - return NULL; -#endif } + return NULL; } -Graphics::Surface* OSystem_DS::createTempFrameBuffer() { +Graphics::Surface *OSystem_DS::createTempFrameBuffer() { // Ensure we copy using 16 bit quantities due to limitation of VRAM addressing @@ -773,13 +761,13 @@ Graphics::Surface* OSystem_DS::createTempFrameBuffer() { s32 width = DS::getGameWidth(); s32 stride = DS::get8BitBackBufferStride(); - u16* src = DS::get8BitBackBuffer(); - u16* dest = DS::getScalerBuffer(); + u16 *src = DS::get8BitBackBuffer(); + u16 *dest = DS::getScalerBuffer(); for (int y = 0; y < height; y++) { - u16* destLine = dest + (y * (width / 2)); - u16* srcLine = src + (y * (stride / 2)); + u16 *destLine = dest + (y * (width / 2)); + u16 *srcLine = src + (y * (stride / 2)); DC_FlushRange(srcLine, width); @@ -800,7 +788,7 @@ Graphics::Surface* OSystem_DS::createTempFrameBuffer() { size_t imageStrideInBytes = DS::get8BitBackBufferStride(); size_t imageStrideInWords = imageStrideInBytes / 2; - u16* image = (u16 *) DS::get8BitBackBuffer(); + u16 *image = (u16 *) DS::get8BitBackBuffer(); for (int y = 0; y < DS::getGameHeight(); y++) { DC_FlushRange(image + (y * imageStrideInWords), DS::getGameWidth()); for (int x = 0; x < DS::getGameWidth() >> 1; x++) { @@ -846,13 +834,13 @@ void OSystem_DS::setCharactersEntered(int count) { DS::setCharactersEntered(count); } -Common::SeekableReadStream* OSystem_DS::createConfigReadStream() { +Common::SeekableReadStream *OSystem_DS::createConfigReadStream() { Common::FSNode file(DEFAULT_CONFIG_FILE); // consolePrintf("R %s", DEFAULT_CONFIG_FILE); return file.createReadStream(); } -Common::WriteStream* OSystem_DS::createConfigWriteStream() { +Common::WriteStream *OSystem_DS::createConfigWriteStream() { Common::FSNode file(DEFAULT_CONFIG_FILE); // consolePrintf("W %s", DEFAULT_CONFIG_FILE); return file.createWriteStream(); diff --git a/backends/platform/ds/arm9/source/osystem_ds.h b/backends/platform/ds/arm9/source/osystem_ds.h index 10b4c87f66..65ac3f4f7e 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.h +++ b/backends/platform/ds/arm9/source/osystem_ds.h @@ -8,15 +8,18 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ @@ -27,7 +30,6 @@ #include "backends/base-backend.h" #include "common/events.h" #include "nds.h" -#include "ramsave.h" #include "gbampsave.h" #include "backends/saves/default/default-saves.h" #include "backends/timer/default/default-timer.h" @@ -44,17 +46,14 @@ protected: Common::Event eventQueue[96]; int queuePos; -#ifdef GBA_SRAM_SAVE - DSSaveFileManager saveManager; -#endif GBAMPSaveFileManager mpSaveManager; - Audio::MixerImpl* _mixer; - DefaultTimerManager* _timer; + Audio::MixerImpl *_mixer; + DefaultTimerManager *_timer; Graphics::Surface _framebuffer; bool _frameBufferExists; bool _graphicsEnable; - static OSystem_DS* _instance; + static OSystem_DS *_instance; u16 _palette[256]; u16 _cursorPalette[256]; @@ -68,7 +67,7 @@ protected: int _cursorScale; - Graphics::Surface* createTempFrameBuffer(); + Graphics::Surface *createTempFrameBuffer(); bool _disableCursorPalette; int _gammaValue; @@ -94,7 +93,7 @@ public: virtual int16 getHeight(); virtual int16 getWidth(); virtual void setPalette(const byte *colors, uint start, uint num); - virtual void grabPalette(unsigned char* colors, uint start, uint num); + virtual void grabPalette(unsigned char *colors, uint start, uint num); void restoreHardwarePalette(); virtual void copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h); @@ -136,10 +135,10 @@ public: virtual Common::SaveFileManager *getSavefileManager(); - void addEvent(Common::Event& e); - bool isEventQueueEmpty() { return queuePos == 0; } + void addEvent(const Common::Event& e); + bool isEventQueueEmpty() const { return queuePos == 0; } - virtual bool grabRawScreen(Graphics::Surface* surf); + virtual bool grabRawScreen(Graphics::Surface *surf); virtual void setFocusRectangle(const Common::Rect& rect); @@ -150,10 +149,10 @@ public: virtual Graphics::Surface *lockScreen(); virtual void unlockScreen(); - virtual Audio::Mixer* getMixer() { return _mixer; } - Audio::MixerImpl* getMixerImpl() { return _mixer; } + virtual Audio::Mixer *getMixer() { return _mixer; } + Audio::MixerImpl *getMixerImpl() { return _mixer; } - virtual Common::TimerManager* getTimerManager() { return _timer; } + virtual Common::TimerManager *getTimerManager() { return _timer; } static int timerHandler(int t); @@ -161,8 +160,8 @@ public: virtual void clearAutoComplete(); virtual void setCharactersEntered(int count); - u16 getDSPaletteEntry(u32 entry) { return _palette[entry]; } - u16 getDSCursorPaletteEntry(u32 entry) { return !_disableCursorPalette? _cursorPalette[entry]: _palette[entry]; } + u16 getDSPaletteEntry(u32 entry) const { return _palette[entry]; } + u16 getDSCursorPaletteEntry(u32 entry) const { return !_disableCursorPalette? _cursorPalette[entry]: _palette[entry]; } virtual void setCursorPalette(const byte *colors, uint start, uint num); @@ -172,8 +171,8 @@ public: void refreshCursor(); - Common::WriteStream* createConfigWriteStream(); - Common::SeekableReadStream* createConfigReadStream(); + Common::WriteStream *createConfigWriteStream(); + Common::SeekableReadStream *createConfigReadStream(); u16 applyGamma(u16 colour); void setGammaValue(int gamma) { _gammaValue = gamma; } diff --git a/backends/platform/ds/arm9/source/portdefs.h b/backends/platform/ds/arm9/source/portdefs.h index 5472b711b8..bdb42993d1 100644 --- a/backends/platform/ds/arm9/source/portdefs.h +++ b/backends/platform/ds/arm9/source/portdefs.h @@ -8,39 +8,26 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ #ifndef _PORTDEFS_H_ #define _PORTDEFS_H_ - - -/* -typedef unsigned char u8; -typedef signed char s8; - -typedef unsigned short u16; -typedef signed short s16; - -typedef unsigned int u32; -typedef signed int s32; -*/ - -#include "nds/ndstypes.h" - - -// Somebody removed these from scummsys.h, but they're still required, so I'm adding them here -// in the hope that they'll stay. +// Somebody removed these from scummsys.h, but they're still required, so I'm +// adding them here in the hope that they'll stay. #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -50,18 +37,20 @@ typedef signed int s32; #define double float -#define CT_NO_TRANSPARENCY - +#ifndef DISABLE_TEXT_CONSOLE #define DISABLE_TEXT_CONSOLE +#endif + +#ifndef DISABLE_COMMAND_LINE #define DISABLE_COMMAND_LINE +#endif +#ifndef STREAM_AUDIO_FROM_DISK #define STREAM_AUDIO_FROM_DISK +#endif -//#undef assert -//#define assert(expr) consolePrintf("Asserted!") #define NO_DEBUG_MSGS - // This is defined in dsmain.cpp #ifdef __cplusplus extern "C" { @@ -76,15 +65,17 @@ void consolePrintf(const char *format, ...); #undef assert #endif -#define assert(s) if (!(s)) consolePrintf("Assertion failed: '##s##' at file %s, line %d\n", __FILE__, __LINE__) +#define assert(s) \ + do { \ + if (!(s)) \ + consolePrintf("Assertion failed: '##s##' at file %s, line %d\n", __FILE__, __LINE__); \ + } while (0) //#include "ds-fs.h" //#define debug(fmt, ...) consolePrintf(fmt, ##__VA_ARGS__) //#define debug(fmt, ...) debug(0, fmt, ##__VA_ARGS__) -#define ITCM_DATA __attribute__((section(".itcm"))) - // FIXME: Since I can't change the engine at the moment (post lockdown) this define can go here. // This define changes the mouse-relative motion which doesn't make sense on a touch screen to // a more conventional form of input where the menus can be clicked on. diff --git a/backends/platform/ds/arm9/source/ramsave.cpp b/backends/platform/ds/arm9/source/ramsave.cpp deleted file mode 100644 index a0f4633988..0000000000 --- a/backends/platform/ds/arm9/source/ramsave.cpp +++ /dev/null @@ -1,538 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ -#ifdef GBA_SRAM_SAVE - - -#include "ramsave.h" -#include "nds.h" -#include "compressor/lz.h" - -#define CART_RAM ((vu8 *) (0x0A000000)) -#define SRAM_SAVE_MAX (65533) - -DSSaveFile::DSSaveFile() { - ptr = 0; - saveCompressed = false; - save.isValid = false; - ownsData = false; - isOpenFlag = true; - isTempFile = false; -} - -DSSaveFile::DSSaveFile(SCUMMSave* s, bool compressed, u8* data) { - save = *s; - saveData = data; - ptr = 0; - saveCompressed = compressed; - isOpenFlag = true; - - if (saveCompressed) { - u8* uncompressed = new unsigned char[save.size]; - if (!uncompressed) consolePrintf("Out of memory allocating %d!\n", save.size); - LZ_Uncompress(saveData, uncompressed, save.compressedSize); - saveData = uncompressed; - ownsData = true; - saveCompressed = false; -// consolePrintf("Decompressed. name=%s size=%d (%d)", save.name, save.size, save.compressedSize); - - } else { - ownsData = false; - origHeader = s; - } - - if (save.magic == (int) 0xBEEFCAFE) { - save.isValid = true; - } else { - save.isValid = false; - } - - isTempFile = false; - eosReached = false; -} - -DSSaveFile::~DSSaveFile() { - if (!ownsData) { - *origHeader = save; - DSSaveFileManager::instance()->flushToSaveRAM(); - } - if (ownsData) { - delete[] saveData; - } -} - -bool DSSaveFile::loadFromSaveRAM(vu8* address) { - - SCUMMSave newSave; - - for (int t = 0; t < (int) sizeof(newSave); t++) { - ((char *) (&newSave))[t] = *(address + t); - } - - if (newSave.magic == 0xBEEFCAFE) { - newSave.isValid = true; - - *((u16 *) (0x4000204)) |= 0x3; - - saveData = new unsigned char[newSave.compressedSize]; - - for (int t = 0; t < (int) newSave.compressedSize; t++) { - ((char *) (saveData))[t] = *(address + t + sizeof(newSave)); - } - - if (ownsData) delete[] this->saveData; - save = newSave; - saveCompressed = true; - this->saveData = saveData; - ownsData = true; - ptr = 0; - - return true; - } - - return false; -} - -void DSSaveFile::compress() { - if (!saveCompressed) { - unsigned char* compBuffer = new unsigned char[(save.size * 110) / 100]; - int compSize = LZ_Compress((u8 *) saveData, compBuffer, save.size); - save.compressedSize = compSize; - - - - delete[] saveData; - - // Make the save smaller - saveData = (u8 *) realloc(compBuffer, save.compressedSize); - saveCompressed = true; - } -} - -int DSSaveFile::saveToSaveRAM(vu8* address) { - - unsigned char* compBuffer; - bool failed; - - - int compSize; - - compress(); - - compSize = save.compressedSize; - compBuffer = saveData; - - if (DSSaveFileManager::instance()->getBytesFree() >= getRamUsage()) { - - DSSaveFileManager::instance()->addBytesFree(-getRamUsage()); - - // Write header - for (int t = 0; t < sizeof(save); t++) { - while (*(address + t) != ((char *) (&save))[t]) { - *(address + t) = ((char *) (&save))[t]; - } - } - - // Write compressed buffer - for (int t = sizeof(save); t < (int) sizeof(save) + compSize; t++) { - while (*(address + t) != compBuffer[t - sizeof(save)]) { - *(address + t) = compBuffer[t - sizeof(save)]; - } - } - - failed = false; - } else { - failed = true; - } - - - return failed? 0: compSize + sizeof(save); - -} - -void DSSaveFile::reset() { - ptr = 0; - eosReached = false; -} - -uint32 DSSaveFile::read(void *buf, uint32 size) { - if (ptr + size > save.size) { - size = save.size - ptr; - eosReached = true; - if (size < 0) size = 0; - } - memcpy(buf, saveData + ptr, size); -// consolePrintf("byte: %d ", ((u8 *) (buf))[0]); - - ptr += size; - return size; -} - -int32 DSSaveFile::pos() const { - return ptr; -} - -int32 DSSaveFile::size() const { - return save.size; -} - -bool DSSaveFile::seek(int32 pos, int whence) { - switch (whence) { - case SEEK_SET: { - ptr = pos; - break; - } - case SEEK_CUR: { - ptr += pos; - break; - } - case SEEK_END: { - ptr = save.size + pos; - break; - } - } - eosReached = false; - return true; -} - -bool DSSaveFile::eos() const { - return eosReached; -} - -void DSSaveFile::clearErr() { - eosReached = false; -} - -bool DSSaveFile::skip(uint32 bytes) { - ptr = ptr + bytes; - if (ptr > (int) save.size) ptr = save.size; - return true; -} - -uint32 DSSaveFile::write(const void *buf, uint32 size) { - - if (ptr + size > DS_MAX_SAVE_SIZE) { - size = DS_MAX_SAVE_SIZE - ptr; - } - - memcpy(saveData + ptr, buf, size); - ptr += size; - save.size += size; - return size; -} - -bool DSSaveFile::matches(const char *prefix, int num) { - char str[16]; - if (isValid()) { - sprintf(str, "%s%02d", prefix, num); - if (!strcmp(str, save.name)) { - return true; - } else { - return false; - } - } else { - return false; - } -} - -bool DSSaveFile::matches(const char *filename) { - if (isValid()) { - return !strcmp(save.name, filename); - } else { - return false; - } -} - -void DSSaveFile::setName(char *name) { - save.isValid = true; - save.magic = 0xBEEFCAFE; - ownsData = true; - save.size = 0; - save.compressedSize = 0; - saveData = new unsigned char[DS_MAX_SAVE_SIZE]; - strcpy(save.name, name); - - if ((strstr(name, ".s99")) || (strstr(name, ".c"))) { - isTempFile = true; - } else { - isTempFile = false; - } -} - -void DSSaveFile::clearData() { - save.size = 0; - - if (saveCompressed) { - if (ownsData) { - delete[] saveData; - DSSaveFileManager::instance()->addBytesFree(getRamUsage()); - } - saveData = new unsigned char[DS_MAX_SAVE_SIZE]; - saveCompressed = false; - ownsData = true; - } - -} - -void DSSaveFile::deleteFile() { - if (isValid()) { - if (ownsData) { - DSSaveFileManager::instance()->addBytesFree(getRamUsage()); - delete[] saveData; - saveData = NULL; - } - ptr = 0; - saveCompressed = false; - save.isValid = false; - ownsData = false; - isOpenFlag = true; - } -} - -DSSaveFileManager::DSSaveFileManager() { - instancePtr = this; - - *((u16 *) (0x4000204)) |= 0x3; - swiWaitForVBlank(); - - loadAllFromSRAM(); -} - -DSSaveFileManager::~DSSaveFileManager() { - instancePtr = NULL; -} - -void DSSaveFileManager::loadAllFromSRAM() { - int addr = 1; - - for (int r = 0; r < 8; r++) { - gbaSave[r].deleteFile(); - } - - sramBytesFree = SRAM_SAVE_MAX; - - // Try to find saves in save RAM - for (int r = 0; r < 8; r++) { - if (gbaSave[r].loadFromSaveRAM(CART_RAM + addr)) { - addr += gbaSave[r].getRamUsage(); - sramBytesFree -= gbaSave[r].getRamUsage(); - } - } - -} - -void DSSaveFileManager::formatSram() { - for (int r = 0; r < SRAM_SAVE_MAX; r++) { - *(CART_RAM + r) = 0; - } - - loadAllFromSRAM(); -} - -void DSSaveFileManager::listFiles() { - for (int r = 0; r < 8; r++) { - if (gbaSave[r].isValid()) { - consolePrintf("'%s': %d bytes\n", gbaSave[r].getName(), gbaSave[r].getRamUsage()); - } - } - consolePrintf("SRAM free: %d bytes\n", getBytesFree()); -} - -DSSaveFileManager* DSSaveFileManager::instancePtr = NULL; - -DSSaveFile *DSSaveFileManager::openSavefile(const char *filename, bool saveOrLoad) { - for (int r = 0; r < 8; r++) { - if (gbaSave[r].isValid() && (gbaSave[r].matches(filename))) { -// consolePrintf("Matched save %d (%d)\n", r, gbaSave[r].getSize()); - gbaSave[r].reset(); - //consolePrintf("reset "); - if (saveOrLoad) gbaSave[r].clearData(); -// consolePrintf("cleared "); - return gbaSave[r].clone(); - } - } - - if (saveOrLoad) { - return makeSaveFile(filename, saveOrLoad); - } else { - return NULL; - } -} - - - -DSSaveFile* DSSaveFile::clone() { -// consolePrintf("Clone %s %d\n", save.name, save.size); - return new DSSaveFile(&save, saveCompressed, saveData); -} - -void DSSaveFileManager::deleteFile(const char* name) { -// consolePrintf("Deleting %s", name); - for (int r = 0; r < 8; r++) { - if (gbaSave[r].isValid() && (gbaSave[r].matches(name))) { - gbaSave[r].deleteFile(); - } - } - flushToSaveRAM(); -} - -bool DSSaveFileManager::removeSavefile(const Common::String &filename) { - consolePrintf("DSSaveFileManager::removeSavefile : Not implemented yet.\n"); - assert(false); - //TODO: Implement this. Most likely, you just have to use the code of deleteFile? - return false; -} - - -Common::StringArray DSSaveFileManager::listSavefiles(const Common::String &pattern) { - consolePrintf("DSSaveFileManager::listSavefiles : Not implemented yet.\n"); - assert(false); - return Common::StringArray(); - /* - TODO: Implement this. If you don't understand what it should do, just ask - (e.g. on scummvm-devel or Fingolfin). It should be pretty simple if you - use Common::matchString from common/util.h and read the Doxygen docs, - then combine this with the old code below... - */ -} - - -/* -void DSSaveFileManager::listSavefiles(const char *prefix, bool *marks, int num) { - memset(marks, true, num * sizeof(bool)); - return; - - memset(marks, false, num*sizeof(bool)); - - for (int saveNum = 0; saveNum < num; saveNum++) { - for (int r = 0; r < 8; r++) { - if (gbaSave[r].isValid() && (gbaSave[r].matches(prefix, saveNum))) { - marks[saveNum] = true; - } - } - } - -} -*/ - - -DSSaveFile *DSSaveFileManager::makeSaveFile(const char *filename, bool saveOrLoad) { - - // Find a free save slot - int r = 0; - - while ((r < 8) && (gbaSave[r].isValid())) { - r++; - } - - if ((r == 8) && (gbaSave[r].isValid())) { - // No more saves - return NULL; - } else { - // Allocate this save -// consolePrintf("Allocated save %d\n", r); - gbaSave[r].setName((char *) filename); - gbaSave[r].reset(); - return gbaSave[r].clone(); - } -} - -void DSSaveFileManager::flushToSaveRAM() { - int cartAddr = 1; - int s; - int extraData = DSSaveFileManager::getExtraData(); - - *((u16 *) (0x4000204)) |= 0x3; - - swiWaitForVBlank(); - - int size = 0; - for (int r = 0; (r < 8); r++) { - if (gbaSave[r].isValid()) { - gbaSave[r].compress(); - if (!gbaSave[r].isTemp()) size += gbaSave[r].getRamUsage(); - } - } - - if (size <= SRAM_SAVE_MAX) { - - for (int r = 0; r < SRAM_SAVE_MAX; r++) { - *(CART_RAM + r) = 0; - } - - sramBytesFree = SRAM_SAVE_MAX; - - for (int r = 0; (r < 8); r++) { - if (gbaSave[r].isValid() && (!gbaSave[r].isTemp())) { - - cartAddr += s = gbaSave[r].saveToSaveRAM(CART_RAM + cartAddr); - - /* if (s == 0) { - consolePrintf("WARNING: Save didn't fit in cart RAM and has been lost!! Delete files and save again.", gbaSave[r].getName()); - failed = true; - }*/ - } - } - } else { - - consolePrintf("WARNING: Save didn't fit in cart RAM and has been lost!! Delete files and save again."); - loadAllFromSRAM(); - - } - - DSSaveFileManager::setExtraData(extraData); -// consolePrintf("SRAM free: %d bytes\n", getBytesFree()); -} - -void DSSaveFileManager::setExtraData(int data) { - // Offset of extra data is 31. This overlaps the padding and reserved bytes of the first save entry. - // which have not been used up until now. So it should be safe. - - vu8* sram = CART_RAM + 31; - - *(sram + 0) = 0xF0; // This is an identifier to check - *(sram + 1) = 0x0D; // that extra data is present. - - *(sram + 2) = (data & 0xFF000000) >> 24; // Now write the actual data - *(sram + 3) = (data & 0x00FF0000) >> 16; // taking care to use single - *(sram + 4) = (data & 0x0000FF00) >> 8; // byte writes (it's an 8-bit bus) - *(sram + 5) = (data & 0x000000FF); -} - -bool DSSaveFileManager::isExtraDataPresent() { - vu8* sram = CART_RAM + 31; - - // Check for the identifier - return ((*(sram + 0) == 0xF0) && (*(sram + 1) == 0x0D)); -} - -int DSSaveFileManager::getExtraData() { - vu8* sram = CART_RAM + 31; - - if (isExtraDataPresent()) { - int value = (*(sram + 2) << 24) | (*(sram + 3) << 16) | (*(sram + 4) << 8) | (*(sram + 5)); - return value; - } else { - return 0; - } -} - -#endif diff --git a/backends/platform/ds/arm9/source/ramsave.h b/backends/platform/ds/arm9/source/ramsave.h deleted file mode 100644 index e74df94952..0000000000 --- a/backends/platform/ds/arm9/source/ramsave.h +++ /dev/null @@ -1,150 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#ifndef _RAMSAVE_H_ -#define _RAMSAVE_H_ - -#include "common/system.h" -#include "common/savefile.h" - -// SaveFileManager class - -#define DS_MAX_SAVE_SIZE 150000 - -class DSSaveFile : public Common::InSaveFile, public Common::OutSaveFile { - int address; - int ptr; - bool ownsData; - bool saveCompressed; - - struct SCUMMSave { - u32 magic; // 4 - bool isValid; // 5 - bool pad; // 6 - char name[16]; // 22 - u32 size; // 26 - u32 compressedSize; // 30 - u16 extraMagic; // 32 - u32 reserved; // 36 - } __attribute__ ((packed)); - - SCUMMSave save; - u8* saveData; - SCUMMSave* origHeader; - bool isOpenFlag; - bool isTempFile; - bool eosReached; - -public: - DSSaveFile(); - DSSaveFile(SCUMMSave* s, bool saveCompressed, u8* data); - ~DSSaveFile(); - - void reset(); - - bool isOpen() const { return isOpenFlag; } - virtual bool eos() const; - virtual void clearErr(); - virtual bool skip(uint32 size); - - virtual int32 pos() const; - virtual int32 size() const; - virtual bool seek(int32 pos, int whence); - - uint32 read(void *buf, uint32 size); - uint32 write(const void *buf, uint32 size); - - void setName(char *name); - char* getName() { return save.name; } - - bool isValid() { return save.isValid; } - bool isTemp() { return isTempFile; } - bool matches(const char *prefix, int num); - bool matches(const char *filename); - - void clearData(); - void compress(); - - int getRamUsage() { return sizeof(save) + save.compressedSize; } - char* getRamImage() { return (char *) &save; } - - int getSize() { return save.size; } - - DSSaveFile* clone(); - - bool loadFromSaveRAM(vu8* address); - int saveToSaveRAM(vu8* address); - - - - void deleteFile(); - - void operator delete(void *p) { -// consolePrintf("Finished! size=%d\n", ((DSSaveFile *) (p))->save->size); - } - - - -}; - - - -class DSSaveFileManager : public Common::SaveFileManager { - - DSSaveFile gbaSave[8]; - static DSSaveFileManager* instancePtr; - int sramBytesFree; - -public: - DSSaveFileManager(); - ~DSSaveFileManager(); - - static DSSaveFileManager* instance() { return instancePtr; } - - DSSaveFile *openSavefile(const char *filename, bool saveOrLoad); - - virtual Common::OutSaveFile* openForSaving(const Common::String &filename) { return openSavefile(filename.c_str(), true); } - virtual Common::InSaveFile* openForLoading(const Common::String &filename) { return openSavefile(filename.c_str(), false); } - - virtual bool removeSavefile(const Common::String &filename); - virtual Common::StringArray listSavefiles(const Common::String &pattern); - - void flushToSaveRAM(); - - void addBytesFree(int size) { sramBytesFree += size; } - int getBytesFree() { return sramBytesFree; } - - void deleteFile(char* name); - void listFiles(); - void formatSram(); - - void loadAllFromSRAM(); - - static bool isExtraDataPresent(); - static int getExtraData(); - static void setExtraData(int data); - -protected: - DSSaveFile *makeSaveFile(const Common::String &filename, bool saveOrLoad); -}; - -#endif diff --git a/backends/platform/ds/arm9/source/scummhelp.cpp b/backends/platform/ds/arm9/source/scummhelp.cpp index e1ddaecc2c..f1e8ba4fb2 100644 --- a/backends/platform/ds/arm9/source/scummhelp.cpp +++ b/backends/platform/ds/arm9/source/scummhelp.cpp @@ -8,15 +8,18 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ @@ -91,7 +94,8 @@ void updateStrings(byte gameId, byte version, Common::Platform platform, } -} +} // End of namespace DS + #undef ADD_BIND diff --git a/backends/platform/ds/arm9/source/scummhelp.h b/backends/platform/ds/arm9/source/scummhelp.h index 602cb5f788..4be28dca6a 100644 --- a/backends/platform/ds/arm9/source/scummhelp.h +++ b/backends/platform/ds/arm9/source/scummhelp.h @@ -8,15 +8,18 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ @@ -31,6 +34,7 @@ namespace DS { void updateStrings(byte gameId, byte version, Common::Platform platform, int page, Common::String &title, Common::String *&key, Common::String *&dsc); -} +} // End of namespace DS + #endif diff --git a/backends/platform/ds/arm9/source/touchkeyboard.cpp b/backends/platform/ds/arm9/source/touchkeyboard.cpp index 2d4b6a94f4..71f4f93c27 100644 --- a/backends/platform/ds/arm9/source/touchkeyboard.cpp +++ b/backends/platform/ds/arm9/source/touchkeyboard.cpp @@ -20,6 +20,7 @@ * */ #include <nds.h> +#include "NDS/scummvm_ipc.h" #include "touchkeyboard.h" #include "keyboard_raw.h" #include "keyboard_pal_raw.h" @@ -43,124 +44,124 @@ struct key_data { #define DS_CAPSLOCK 1 -key_data keys[DS_NUM_KEYS] = { +static key_data keys[DS_NUM_KEYS] = { // Key number x y character // Numbers - {28, 3, 0, '1'}, - {29, 5, 0, '2'}, - {30, 7, 0, '3'}, - {31, 9, 0, '4'}, - {32, 11, 0, '5'}, - {33, 13, 0, '6'}, - {34, 15, 0, '7'}, - {35, 17, 0, '8'}, - {36, 19, 0, '9'}, - {27, 21, 0, '0'}, - {45, 23, 0, Common::KEYCODE_MINUS}, - {50, 25, 0, Common::KEYCODE_EQUALS}, - {52, 27, 0, Common::KEYCODE_BACKSPACE}, + {28, 3, 0, '1', false}, + {29, 5, 0, '2', false}, + {30, 7, 0, '3', false}, + {31, 9, 0, '4', false}, + {32, 11, 0, '5', false}, + {33, 13, 0, '6', false}, + {34, 15, 0, '7', false}, + {35, 17, 0, '8', false}, + {36, 19, 0, '9', false}, + {27, 21, 0, '0', false}, + {45, 23, 0, Common::KEYCODE_MINUS, false}, + {50, 25, 0, Common::KEYCODE_EQUALS, false}, + {52, 27, 0, Common::KEYCODE_BACKSPACE, false}, // Top row - {'Q'-'A' + 1, 4, 2, 'Q'}, - {'W'-'A' + 1, 6, 2, 'W'}, - {'E'-'A' + 1, 8, 2, 'E'}, - {'R'-'A' + 1, 10, 2, 'R'}, - {'T'-'A' + 1, 12, 2, 'T'}, - {'Y'-'A' + 1, 14, 2, 'Y'}, - {'U'-'A' + 1, 16, 2, 'U'}, - {'I'-'A' + 1, 18, 2, 'I'}, - {'O'-'A' + 1, 20, 2, 'O'}, - {'P'-'A' + 1, 22, 2, 'P'}, - {43, 24, 2, Common::KEYCODE_LEFTBRACKET}, - {44, 26, 2, Common::KEYCODE_RIGHTBRACKET}, + {'Q'-'A' + 1, 4, 2, 'Q', false}, + {'W'-'A' + 1, 6, 2, 'W', false}, + {'E'-'A' + 1, 8, 2, 'E', false}, + {'R'-'A' + 1, 10, 2, 'R', false}, + {'T'-'A' + 1, 12, 2, 'T', false}, + {'Y'-'A' + 1, 14, 2, 'Y', false}, + {'U'-'A' + 1, 16, 2, 'U', false}, + {'I'-'A' + 1, 18, 2, 'I', false}, + {'O'-'A' + 1, 20, 2, 'O', false}, + {'P'-'A' + 1, 22, 2, 'P', false}, + {43, 24, 2, Common::KEYCODE_LEFTBRACKET, false}, + {44, 26, 2, Common::KEYCODE_RIGHTBRACKET, false}, // Middle row - {55, 3, 4, DS_CAPSLOCK}, - {'A'-'A' + 1, 5, 4, 'A'}, - {'S'-'A' + 1, 7, 4, 'S'}, - {'D'-'A' + 1, 9, 4, 'D'}, - {'F'-'A' + 1, 11, 4, 'F'}, - {'G'-'A' + 1, 13, 4, 'G'}, - {'H'-'A' + 1, 15, 4, 'H'}, - {'J'-'A' + 1, 17, 4, 'J'}, - {'K'-'A' + 1, 19, 4, 'K'}, - {'L'-'A' + 1, 21, 4, 'L'}, - {42, 23, 4, Common::KEYCODE_SEMICOLON}, - {41, 25, 4, Common::KEYCODE_QUOTE}, - {46, 27, 4, Common::KEYCODE_RETURN}, + {55, 3, 4, DS_CAPSLOCK, false}, + {'A'-'A' + 1, 5, 4, 'A', false}, + {'S'-'A' + 1, 7, 4, 'S', false}, + {'D'-'A' + 1, 9, 4, 'D', false}, + {'F'-'A' + 1, 11, 4, 'F', false}, + {'G'-'A' + 1, 13, 4, 'G', false}, + {'H'-'A' + 1, 15, 4, 'H', false}, + {'J'-'A' + 1, 17, 4, 'J', false}, + {'K'-'A' + 1, 19, 4, 'K', false}, + {'L'-'A' + 1, 21, 4, 'L', false}, + {42, 23, 4, Common::KEYCODE_SEMICOLON, false}, + {41, 25, 4, Common::KEYCODE_QUOTE, false}, + {46, 27, 4, Common::KEYCODE_RETURN, false}, // Bottom row - {51, 4, 6, DS_SHIFT}, - {'Z'-'A' + 1, 6, 6, 'Z'}, - {'X'-'A' + 1, 8, 6, 'X'}, - {'C'-'A' + 1, 10, 6, 'C'}, - {'V'-'A' + 1, 12, 6, 'V'}, - {'B'-'A' + 1, 14, 6, 'B'}, - {'N'-'A' + 1, 16, 6, 'N'}, - {'M'-'A' + 1, 18, 6, 'M'}, - {38, 20, 6, Common::KEYCODE_COMMA}, - {39, 22, 6, Common::KEYCODE_PERIOD}, - {40, 24, 6, Common::KEYCODE_SLASH}, + {51, 4, 6, DS_SHIFT, false}, + {'Z'-'A' + 1, 6, 6, 'Z', false}, + {'X'-'A' + 1, 8, 6, 'X', false}, + {'C'-'A' + 1, 10, 6, 'C', false}, + {'V'-'A' + 1, 12, 6, 'V', false}, + {'B'-'A' + 1, 14, 6, 'B', false}, + {'N'-'A' + 1, 16, 6, 'N', false}, + {'M'-'A' + 1, 18, 6, 'M', false}, + {38, 20, 6, Common::KEYCODE_COMMA, false}, + {39, 22, 6, Common::KEYCODE_PERIOD, false}, + {40, 24, 6, Common::KEYCODE_SLASH, false}, // Space bar - {47, 9, 8, Common::KEYCODE_SPACE}, - {48, 11, 8, Common::KEYCODE_SPACE}, - {48, 13, 8, Common::KEYCODE_SPACE}, - {48, 15, 8, Common::KEYCODE_SPACE}, - {48, 17, 8, Common::KEYCODE_SPACE}, - {49, 19, 8, Common::KEYCODE_SPACE}, + {47, 9, 8, Common::KEYCODE_SPACE, false}, + {48, 11, 8, Common::KEYCODE_SPACE, false}, + {48, 13, 8, Common::KEYCODE_SPACE, false}, + {48, 15, 8, Common::KEYCODE_SPACE, false}, + {48, 17, 8, Common::KEYCODE_SPACE, false}, + {49, 19, 8, Common::KEYCODE_SPACE, false}, // Cursor arrows - {52, 27, 8, Common::KEYCODE_LEFT}, - {54, 29, 8, Common::KEYCODE_DOWN}, - {53, 31, 8, Common::KEYCODE_RIGHT}, - {51, 29, 6, Common::KEYCODE_UP}, + {52, 27, 8, Common::KEYCODE_LEFT, false}, + {54, 29, 8, Common::KEYCODE_DOWN, false}, + {53, 31, 8, Common::KEYCODE_RIGHT, false}, + {51, 29, 6, Common::KEYCODE_UP, false}, // Close button - {56, 30, 0, Common::KEYCODE_INVALID}, + {56, 30, 0, Common::KEYCODE_INVALID, false}, // Function keys (needed for AGI) - {57, 4, -2, Common::KEYCODE_F1}, - {58, 6, -2, Common::KEYCODE_F2}, - {59, 8, -2, Common::KEYCODE_F3}, - {60, 10, -2, Common::KEYCODE_F4}, - {61, 14, -2, Common::KEYCODE_F5}, - {62, 16, -2, Common::KEYCODE_F6}, - {63, 18, -2, Common::KEYCODE_F7}, - {64, 20, -2, Common::KEYCODE_F8}, - {65, 24, -2, Common::KEYCODE_F9}, - {66, 26, -2, Common::KEYCODE_F10}, - {67, 28, -2, Common::KEYCODE_F11}, - {68, 30, -2, Common::KEYCODE_F12}, + {57, 4, -2, Common::KEYCODE_F1, false}, + {58, 6, -2, Common::KEYCODE_F2, false}, + {59, 8, -2, Common::KEYCODE_F3, false}, + {60, 10, -2, Common::KEYCODE_F4, false}, + {61, 14, -2, Common::KEYCODE_F5, false}, + {62, 16, -2, Common::KEYCODE_F6, false}, + {63, 18, -2, Common::KEYCODE_F7, false}, + {64, 20, -2, Common::KEYCODE_F8, false}, + {65, 24, -2, Common::KEYCODE_F9, false}, + {66, 26, -2, Common::KEYCODE_F10, false}, + {67, 28, -2, Common::KEYCODE_F11, false}, + {68, 30, -2, Common::KEYCODE_F12, false}, }; -int keyboardX; -int keyboardY; +static int keyboardX; +static int keyboardY; -int mapBase; -int tileBase; +static int s_mapBase; +static int s_tileBase; -u16* baseAddress; +static u16 *baseAddress; -bool shiftState; -bool capsLockState; +static bool shiftState; +static bool capsLockState; -bool closed; +static bool closed; -char autoCompleteWord[NUM_WORDS][32]; -int autoCompleteCount; +static char autoCompleteWord[NUM_WORDS][32]; +static int autoCompleteCount; -char autoCompleteBuffer[128]; +static char autoCompleteBuffer[128]; -int selectedCompletion = -1; -int charactersEntered = 0; -int typingTimeout = 0; +static int selectedCompletion = -1; +static int charactersEntered = 0; +static int typingTimeout = 0; // Render text onto the tiled screen -void drawText(int tx, int ty, char* string, bool highlight) { +void drawText(int tx, int ty, const char *string, bool highlight) { u16 baseValue = 0; @@ -181,7 +182,7 @@ void drawText(int tx, int ty, char* string, bool highlight) { -void restoreVRAM(int tileBase, int mapBase, u16* saveSpace) { +void restoreVRAM(int tileBase, int mapBase, u16 *saveSpace) { /* for (int r = 0; r < 32 * 32; r++) { ((u16 *) SCREEN_BASE_BLOCK_SUB(mapBase))[r] = *saveSpace++; } @@ -191,7 +192,7 @@ void restoreVRAM(int tileBase, int mapBase, u16* saveSpace) { }*/ } -void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) { +void drawKeyboard(int tileBase, int mapBase, u16 *saveSpace) { /* int keyboardDataSize = 4736 * 2; */ for (int r = 0; r < 32 * 32; r++) { @@ -211,8 +212,8 @@ void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) { // this is the font for (int tile = 0; tile < 94; tile++) { - u16* tileAddr = (u16 *) (CHAR_BASE_BLOCK_SUB(tileBase) + ((KEYBOARD_DATA_SIZE) + (tile * 32))); - u8* src = ((u8 *) (::_8x8font_tga_raw)) + 18 + tile * 8; + u16 *tileAddr = (u16 *) (CHAR_BASE_BLOCK_SUB(tileBase) + ((KEYBOARD_DATA_SIZE) + (tile * 32))); + const u8 *src = ((const u8 *) (::_8x8font_tga_raw)) + 18 + tile * 8; for (int y = 0 ; y < 8; y++) { for (int x = 0; x < 2; x++) { @@ -247,8 +248,8 @@ void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) { keyboardX = -2; keyboardY = 2; - DS::mapBase = mapBase; - DS::tileBase = tileBase; + DS::s_mapBase = mapBase; + DS::s_tileBase = tileBase; shiftState = false; capsLockState = false; @@ -256,7 +257,7 @@ void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) { int x = keyboardX; int y = keyboardY; - u16* base = ((u16 *) SCREEN_BASE_BLOCK_SUB(mapBase)); + u16 *base = ((u16 *) SCREEN_BASE_BLOCK_SUB(mapBase)); baseAddress = base; for (int r = 0; r < DS_NUM_KEYS; r++) { @@ -314,7 +315,7 @@ bool getKeyboardClosed() { } void setKeyHighlight(int key, bool highlight) { - u16* base = ((u16 *) SCREEN_BASE_BLOCK_SUB(DS::mapBase)); + u16 *base = ((u16 *) SCREEN_BASE_BLOCK_SUB(DS::s_mapBase)); if (highlight) { base[(keyboardY + keys[key].y) * 32 + keyboardX + keys[key].x] |= 0x1000; @@ -329,7 +330,7 @@ void setKeyHighlight(int key, bool highlight) { } } -void addAutoComplete(const char* word) { +void addAutoComplete(const char *word) { if (autoCompleteCount == NUM_WORDS) return; strcpy(&autoCompleteWord[autoCompleteCount++][0], word); drawAutoComplete(); @@ -353,7 +354,7 @@ void clearAutoComplete() { void typeCompletion(int current) { Common::Event event; - /* OSystem_DS* system = OSystem_DS::instance(); */ + /* OSystem_DS *system = OSystem_DS::instance(); */ strcat(autoCompleteBuffer, &autoCompleteWord[current][charactersEntered]); strcat(autoCompleteBuffer, " "); @@ -384,7 +385,7 @@ void typeCompletion(int current) { void updateTypeEvents() { if (autoCompleteBuffer[0] != '\0') { Common::Event event; - OSystem_DS* system = OSystem_DS::instance(); + OSystem_DS *system = OSystem_DS::instance(); event.kbd.keycode = (Common::KeyCode) autoCompleteBuffer[0]; event.kbd.ascii = autoCompleteBuffer[0]; @@ -395,8 +396,7 @@ void updateTypeEvents() { event.type = Common::EVENT_KEYUP; system->addEvent(event); - for (int r = 0; r < (int)strlen(autoCompleteBuffer); r++) - { + for (int r = 0; r < (int)strlen(autoCompleteBuffer); r++) { autoCompleteBuffer[r] = autoCompleteBuffer[r + 1]; } @@ -404,8 +404,7 @@ void updateTypeEvents() { } } -void createKeyEvent(int keyNum, Common::Event& event) -{ +void createKeyEvent(int keyNum, Common::Event& event) { event.kbd.flags = 0; if ((keys[keyNum].character >= '0') && (keys[keyNum].character <= '9')) { @@ -443,7 +442,7 @@ void releaseAllKeys() { if (keys[r].pressed) { DS::setKeyHighlight(r, false); - OSystem_DS* system = OSystem_DS::instance(); + OSystem_DS *system = OSystem_DS::instance(); Common::Event event; createKeyEvent(r, event); @@ -502,7 +501,7 @@ void addKeyboardEvents() { for (int r = 0; r < DS_NUM_KEYS; r++) { if (( (tx >= keys[r].x) && (tx <= keys[r].x + 1)) && (ty >= keys[r].y) && (ty <= keys[r].y + 1)) { - OSystem_DS* system = OSystem_DS::instance(); + OSystem_DS *system = OSystem_DS::instance(); Common::Event event; // consolePrintf("Key: %d\n", r); @@ -551,7 +550,7 @@ void addKeyboardEvents() { if (keys[r].pressed) { DS::setKeyHighlight(r, false); - OSystem_DS* system = OSystem_DS::instance(); + OSystem_DS *system = OSystem_DS::instance(); Common::Event event; if ((keys[r].character == Common::KEYCODE_INVALID)) { @@ -586,5 +585,4 @@ void addKeyboardEvents() { } -} - +} // End of namespace DS diff --git a/backends/platform/ds/arm9/source/touchkeyboard.h b/backends/platform/ds/arm9/source/touchkeyboard.h index 6ceb83bfc7..7644e48bff 100644 --- a/backends/platform/ds/arm9/source/touchkeyboard.h +++ b/backends/platform/ds/arm9/source/touchkeyboard.h @@ -8,15 +8,18 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ @@ -27,23 +30,25 @@ namespace DS { -static const int NUM_WORDS = 12; -static const int KEYBOARD_DATA_SIZE = 4736 * 2; -static const int KEYBOARD_BOTTOM_Y = 105; +enum { + NUM_WORDS = 12, + KEYBOARD_DATA_SIZE = 4736 * 2, + KEYBOARD_BOTTOM_Y = 105 +}; void createKeyEvent(int keyNum, Common::Event& event); -void drawKeyboard(int tileBase, int mapBase, u16* saveSpace); -void restoreVRAM(int tileBase, int mapBase, u16* saveSpace); +void drawKeyboard(int tileBase, int mapBase, u16 *saveSpace); +void restoreVRAM(int tileBase, int mapBase, u16 *saveSpace); void addKeyboardEvents(); bool getKeyboardClosed(); bool isInsideKeyboard(int x, int y); -void addAutoComplete(const char* word); +void addAutoComplete(const char *word); void clearAutoComplete(); void setCharactersEntered(int count); void releaseAllKeys(); -} +} // End of namespace DS #endif diff --git a/backends/platform/ds/arm9/source/wordcompletion.cpp b/backends/platform/ds/arm9/source/wordcompletion.cpp index 035f6a631d..43a16486c5 100644 --- a/backends/platform/ds/arm9/source/wordcompletion.cpp +++ b/backends/platform/ds/arm9/source/wordcompletion.cpp @@ -1,3 +1,28 @@ +/* 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 "wordcompletion.h" #include "osystem_ds.h" #include "engines/agi/agi.h" // Caution for #define for NUM_CHANNELS, causes problems in mixer_intern.h @@ -14,7 +39,7 @@ namespace DS { char wordBuffer[WORD_BUFFER_SIZE]; int wordBufferPos = 0; -char* wordBufferPtr[MAX_WORD_COUNT]; +char *wordBufferPtr[MAX_WORD_COUNT]; int wordBufferPtrPos = 0; void addAutoCompleteLine(const char *line) { @@ -53,7 +78,7 @@ void addAutoCompleteLine(const char *line) { } } -int stringCompare(const void* a, const void* b) { +int stringCompare(const void *a, const void *b) { const char** as = (const char **) a; const char** bs = (const char **) b; @@ -71,7 +96,7 @@ void sortAutoCompleteWordList() { } // Sends the current available words to the virtual keyboard code for display -bool findWordCompletions(const char* input) { +bool findWordCompletions(const char *input) { int min = 0; int max = wordBufferPtrPos - 1; char *word; @@ -82,7 +107,7 @@ bool findWordCompletions(const char* input) { if (wordBufferPtrPos == 0) return false; - OSystem_DS* system = (OSystem_DS *) g_system; + OSystem_DS *system = (OSystem_DS *) g_system; system->clearAutoComplete(); int start = 0; @@ -176,5 +201,6 @@ bool findWordCompletions(const char* input) { } -} +} // End of namespace DS + #endif diff --git a/backends/platform/ds/arm9/source/wordcompletion.h b/backends/platform/ds/arm9/source/wordcompletion.h index e50bade37b..55a0bc8b5a 100644 --- a/backends/platform/ds/arm9/source/wordcompletion.h +++ b/backends/platform/ds/arm9/source/wordcompletion.h @@ -1,3 +1,28 @@ +/* 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$ + * + */ + namespace DS { extern void clearAutoCompleteWordList(); @@ -5,4 +30,4 @@ extern bool findWordCompletions(const char *input); extern void addAutoCompleteLine(const char *line); extern void sortAutoCompleteWordList(); -} +} // End of namespace DS diff --git a/backends/platform/ds/arm9/source/zipreader.cpp b/backends/platform/ds/arm9/source/zipreader.cpp index fd6da4e9b9..d4f055ee82 100644 --- a/backends/platform/ds/arm9/source/zipreader.cpp +++ b/backends/platform/ds/arm9/source/zipreader.cpp @@ -8,19 +8,23 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ +#include "common/scummsys.h" #include "zipreader.h" ZipFile::ZipFile() { @@ -28,7 +32,7 @@ ZipFile::ZipFile() { // consolePrintf("ZIP file check..."); - char* p = (char *) ZF_SEARCH_START; + char *p = (char *) ZF_SEARCH_START; bool found = false; _zipFile = NULL; @@ -75,7 +79,6 @@ bool ZipFile::restartFile() { bool more = true; while (!currentFileInFolder() && more) { - char name[128]; getFileName(name); more = skipFile(); } @@ -112,7 +115,7 @@ bool ZipFile::currentFileInFolder() { return false; } -void ZipFile::getFileName(char* name) { +void ZipFile::getFileName(char *name) { strncpy(name, (char *) (_currentFile + 1), _currentFile->nameLength); for (int r = 0; name[r] != 0; r++) { @@ -207,7 +210,7 @@ void ZipFile::changeToRoot() { _directory[0] = 0; } -void ZipFile::changeDirectory(const char* dir) { +void ZipFile::changeDirectory(const char *dir) { // consolePrintf("Current dir now '%s'\n", dir); assert(dir && *dir); diff --git a/backends/platform/ds/arm9/source/zipreader.h b/backends/platform/ds/arm9/source/zipreader.h index d1f70942ce..5429954088 100644 --- a/backends/platform/ds/arm9/source/zipreader.h +++ b/backends/platform/ds/arm9/source/zipreader.h @@ -8,21 +8,26 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ #ifndef _ZIPREADER_H_ #define _ZIPREADER_H_ -#include "portdefs.h" + +#include <nds/ndstypes.h> + #define ZF_SEARCH_START 0x08000000 #define ZF_SEARCH_END 0x09000000 #define ZF_SEARCH_STRIDE 16 @@ -43,12 +48,12 @@ class ZipFile { u16 extraLength; // Length of any extra data } __attribute__ ((packed)); - char* _zipFile; + char *_zipFile; char _directory[128]; bool _allFilesVisible; - FileHeader* _currentFile; + FileHeader *_currentFile; public: ZipFile(); @@ -61,13 +66,13 @@ public: bool findFile(const char *search); // These return the file's data and information - char* getFile(); + char *getFile(); int getFileSize(); - void getFileName(char* name); + void getFileName(char *name); bool isDirectory(); // These set the current directory - void changeDirectory(const char* name); + void changeDirectory(const char *name); void changeToRoot(); void setAllFilesVisible(bool state) { _allFilesVisible = state; } diff --git a/backends/platform/ds/commoninclude/NDS/scummvm_ipc.h b/backends/platform/ds/commoninclude/NDS/scummvm_ipc.h index f41548f400..cf6436634a 100644 --- a/backends/platform/ds/commoninclude/NDS/scummvm_ipc.h +++ b/backends/platform/ds/commoninclude/NDS/scummvm_ipc.h @@ -33,34 +33,32 @@ ////////////////////////////////////////////////////////////////////// -typedef struct sTransferSoundData { -//--------------------------------------------------------------------------------- - const void *data; - u32 len; - u32 rate; - u8 vol; - u8 pan; - u8 format; - u8 PADDING; -} TransferSoundData, * pTransferSoundData; +typedef struct { + const void *data; + u32 len; + u32 rate; + u8 vol; + u8 pan; + u8 format; + u8 PADDING; +} TransferSoundData; //--------------------------------------------------------------------------------- -typedef struct sTransferSound { -//--------------------------------------------------------------------------------- - TransferSoundData data[16]; - u8 count; - u8 PADDING[3]; -} TransferSound, * pTransferSound; +typedef struct { + TransferSoundData data[16]; + u8 count; + u8 PADDING[3]; +} TransferSound; -typedef struct _adpcmBuffer { - u8* buffer[8]; +typedef struct { + u8 *buffer[8]; bool filled[8]; - u8* arm7Buffer[8]; + u8 *arm7Buffer[8]; bool arm7Dirty[8]; bool semaphore; } adpcmBuffer; @@ -82,22 +80,22 @@ typedef struct scummvmTransferRegion { uint8 curtime[8]; // current time response from RTC struct { - u8 rtc_command; - u8 rtc_year; //add 2000 to get 4 digit year - u8 rtc_month; //1 to 12 - u8 rtc_day; //1 to (days in month) - - u8 rtc_incr; - u8 rtc_hours; //0 to 11 for AM, 52 to 63 for PM - u8 rtc_minutes; //0 to 59 - u8 rtc_seconds; //0 to 59 - }; + u8 command; + u8 year; //add 2000 to get 4 digit year + u8 month; //1 to 12 + u8 day; //1 to (days in month) + + u8 incr; + u8 hours; //0 to 11 for AM, 52 to 63 for PM + u8 minutes; //0 to 59 + u8 seconds; //0 to 59 + } rtc; }; uint16 battery; // battery life ?? hopefully. :) uint16 aux; // i have no idea... - pTransferSound soundData; + TransferSound *soundData; adpcmBuffer adpcm; @@ -127,7 +125,7 @@ typedef struct scummvmTransferRegion { // Streaming sound bool streamFillNeeded[4]; int streamPlayingSection; -} scummTransferRegion, * pscummTransferRegion; +} scummTransferRegion; ////////////////////////////////////////////////////////////////////// diff --git a/backends/platform/ds/ds.mk b/backends/platform/ds/ds.mk index aeba1820c6..27309663d1 100644 --- a/backends/platform/ds/ds.mk +++ b/backends/platform/ds/ds.mk @@ -1,12 +1,64 @@ -# Repeat "all" target here, to make sure it is the first target -# Currently disabled, so only arm7.bin gets build -#all: +# To approximate the DS builds A, B, C, ... run our configure like this +# configure --host=ds --disable-translation --disable-all-engines OPTIONS +# where OPTIONS is... +# build A: --enable-scumm +# build B: --enable-sky --enable-queen +# build C: --enable-agos +# build D: --enable-gob --enable-cine --enable-agi +# build E: --enable-saga --disable-mad +# build F: --enable-kyra --disable-mad +# build G: --enable-lure +# build H: --enable-parallaction +# build I: --enable-made --disable-mad +# build K: --enable-cruise --disable-mad +# +# This does not currently take care of some things: +# * It does not #define DS_BUILD_A etc. -- most uses of that should be +# eliminated, though. Only usage should be for selecting the default config +# file (and for that we should really rather allow overriding the value of +# DEFAULT_CONFIG_FILE). +# There are a few game specific hacks which are currently controlled by this, +# too; we need to investigate those. +# * It does not currently adjust the logo. Ideally, if we ever get real plugin +# support, that should be necessary anymore anyway. +# * ... + +# Set location of ndsdir so that we can easily refer to files in it +ndsdir = backends/platform/ds + + +# Until we fix logo support, always use the A logo +LOGO = logoa.bmp + +# Uncomment the following line to enable support for the +# ace DS Debugger (remembering to make the same change in the arm7 makefile): +#USE_DEBUGGER = 1 +# TODO: Need to reimplement this (for arm9 and arm7). +#ifdef USE_DEBUGGER +# DEFINES += -DUSE_DEBUGGER +# CFLAGS += -g +#endif +# Uncomment the following line to enable the profiler +#USE_PROFILER = 1 +# TODO: Need to reimplement this; and maybe replace it by the --enable-profiling +# configure directive. Below is USE_PROFILER related code from the old NDS +# build system: +#ifdef USE_PROFILER +# CFLAGS += -mpoke-function-name -finstrument-functions -g +# DEFINES += -DUSE_PROFILER +#endif +# And this for module.mk: +#ifdef USE_PROFILER +# PORT_OBJS += arm9/source/profiler/cyg-profile.o +#endif + + + +# NOTE: The header and libs for the debugger is assumed to be in the libnds +# folder. -# Files in this list will be optimisied for speed, otherwise they will be optimised for space -OPTLIST := actor.cpp ds_main.cpp osystem_ds.cpp blitters.cpp fmopl.cpp rate.cpp isomap.cpp image.cpp gfx.cpp sprite.cpp actor_path.cpp actor_walk.cpp -#OPTLIST := # Compiler options for files which should be optimised for speed OPT_SPEED := -O3 @@ -14,31 +66,71 @@ OPT_SPEED := -O3 # Compiler options for files which should be optimised for space OPT_SIZE := -Os -mthumb +# By default optimize for size +CXXFLAGS += $(OPT_SIZE) + +# Files listed below will be optimisied for speed, otherwise they will be optimised for space +# TODO: speed original list contained three more files that should be optimized +# for speed: actor.cpp gfx.cpp sprite.cpp -- but there are many files with these +# names, which are the "right" ones? +$(ndsdir)/arm9/source/dsmain.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +$(ndsdir)/arm9/source/osystem_ds.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +$(ndsdir)/arm9/source/blitters.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +$(ndsdir)/arm9/source/ds_main.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +engines/saga/isomap.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +sound/rate.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +engines/saga/actor_walk.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +engines/saga/actor_path.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +engines/saga/image.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +sound/fmopl.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +engines/saga/actor.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +engines/scumm/actor.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +engines/m4/actor.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +engines/scumm/gfx.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +engines/cine/gfx.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +engines/agos/gfx.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +engines/saga/gfx.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +engines/saga/sprite.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +engines/m4/sprite.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +engines/agi/sprite.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) +# TODO: Fingolfin says: optimizing staticres for size would +# save about 30k, so maybe consider that? +#engines/kyra/staticres.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED) -#-mthumb -fno-gcse -fno-schedule-insns2 -OBJS := $(DATA_OBJS) $(LIBCARTRESET_OBJS) $(PORT_OBJS) $(COMPRESSOR_OBJS) $(FAT_OBJS) +############################################################################# +# +# ARM9 rules. +# +############################################################################# + +all: scummvm.nds scummvm.ds.gba +clean: dsclean -# TODO: Handle files in OPTLIST. -# For this, the list should be made explicit. So, replace actor.cpp by path/to/actor.cpp -- -# in fact, there are several actor.cpp files, and right now all are "optimized", but -# I think Neil only had the SAGA one in mind. Same for gfx.cpp +dsclean: + $(RM) $(addprefix $(ndsdir)/, $(ARM7_MODULE_OBJS)) scummvm.nds scummvm.ds.gba +.PHONY: dsclean +# TODO: Add a 'dsdist' target ? +%.bin: %.elf + $(OBJCOPY) -S -O binary $< $@ +%.nds: %.bin $(ndsdir)/arm7/arm7.bin + ndstool -c $@ -9 $< -7 $(ndsdir)/arm7/arm7.bin -b $(srcdir)/$(ndsdir)/$(LOGO) "$(@F);ScummVM $(VERSION);DS Port" +%.ds.gba: %.nds + dsbuild $< -o $@ -l $(srcdir)/$(ndsdir)/arm9/ndsloader.bin + padbin 16 $@ ############################################################################# ############################################################################# ############################################################################# -#ndsdir = $(srcdir)/backends/platform/ds -ndsdir = backends/platform/ds - ############################################################################# # # ARM7 rules. @@ -47,12 +139,6 @@ ndsdir = backends/platform/ds # ############################################################################# -$(ndsdir)/arm7/arm7.bin: $(ndsdir)/arm7/arm7.elf - -$(ndsdir)/arm7/arm7.elf: \ - $(ndsdir)/arm7/source/libcartreset/cartreset.o \ - $(ndsdir)/arm7/source/main.o - # HACK/FIXME: C compiler, for cartreset.c -- we should switch this to use CXX # as soon as possible. CC := $(DEVKITARM)/bin/arm-eabi-gcc @@ -65,7 +151,7 @@ OBJCOPY := $(DEVKITARM)/bin/arm-eabi-objcopy # ARM7_ARCH := -mthumb-interwork -# note: arm9tdmi isn't the correct CPU arch, but anything newer and LD +# note: arm7tdmi isn't the correct CPU arch, but anything newer and LD # *insists* it has a FPU or VFP, and it won't take no for an answer! ARM7_CFLAGS := -g -Wall -O2\ -mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\ @@ -89,7 +175,6 @@ ARM7_LDFLAGS := -g $(ARM7_ARCH) -mno-fpu $(MKDIR) $(*D)/$(DEPDIR) $(CC) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o - # Set custom build flags for cartreset.o $(ndsdir)/arm7/source/libcartreset/cartreset.o: CXXFLAGS=$(ARM7_CFLAGS) $(ndsdir)/arm7/source/libcartreset/cartreset.o: CPPFLAGS= @@ -98,14 +183,28 @@ $(ndsdir)/arm7/source/libcartreset/cartreset.o: CPPFLAGS= $(ndsdir)/arm7/source/main.o: CXXFLAGS=$(ARM7_CXXFLAGS) $(ndsdir)/arm7/source/main.o: CPPFLAGS= +# Rule for creating ARM7 .elf files by linking .o files together with a special linker script +$(ndsdir)/arm7/arm7.elf: \ + $(ndsdir)/arm7/source/libcartreset/cartreset.o \ + $(ndsdir)/arm7/source/main.o + $(CXX) $(ARM7_LDFLAGS) -specs=ds_arm7.specs $+ -L$(DEVKITPRO)/libnds/lib -lnds7 -o $@ + # Rule for creating ARM7 .bin files from .elf files -%.bin: %.elf - @echo ------ - @echo Building $@... +$(ndsdir)/arm7/arm7.bin: $(ndsdir)/arm7/arm7.elf $(OBJCOPY) -O binary $< $@ -# Rule for creating ARM7 .elf files by linking .o files together with a special linker script -%.elf: - @echo ------ - @echo Building $@... - $(CXX) $(ARM7_LDFLAGS) -specs=ds_arm7.specs $+ -L/opt/devkitPro/libnds/lib -lnds7 -o $@ + + + + + + +# Command to build libmad is: +# ./configure --host=arm-elf --enable-speed --enable-sso -enable-fpm=arm CFLAGS='-specs=ds_arm9.specs -mthumb-interwork' +# +# I actually had to use +# ./configure --host=arm-elf --enable-speed --enable-sso -enable-fpm=arm CFLAGS='-specs=ds_arm9.specs -mthumb-interwork' LDFLAGS='C:/Progra~1/devkitpro/libnds/lib/libnds9.a' --disable-shared --disable-debugging +# +# Fingolfin used +# CXX=arm-eabi-g++ CC=arm-eabi-gcc ./configure --host=arm-elf --enable-speed --enable-sso -enable-fpm=arm CFLAGS='-specs=ds_arm9.specs -mthumb-interwork' --disable-shared --disable-debugging LDFLAGS=$DEVKITPRO/libnds/lib/libnds9.a + diff --git a/backends/platform/ds/module.mk b/backends/platform/ds/module.mk index 16630dc070..f6b69b3633 100644 --- a/backends/platform/ds/module.mk +++ b/backends/platform/ds/module.mk @@ -12,8 +12,6 @@ PORT_OBJS := \ arm9/source/gbampsave.o \ arm9/source/scummhelp.o \ arm9/source/osystem_ds.o \ - arm9/source/portdefs.o \ - arm9/source/ramsave.o \ arm9/source/touchkeyboard.o \ arm9/source/zipreader.o \ arm9/source/dsoptions.o \ @@ -21,10 +19,6 @@ PORT_OBJS := \ arm9/source/wordcompletion.o \ arm9/source/interrupt.o -ifdef USE_PROFILER - PORT_OBJS += arm9/source/profiler/cyg-profile.o -endif - DATA_OBJS := \ arm9/data/icons.o \ arm9/data/keyboard.o \ @@ -32,9 +26,9 @@ DATA_OBJS := \ arm9/data/default_font.o \ arm9/data/8x8font_tga.o -COMPRESSOR_OBJS := #arm9/source/compressor/lz.o - -FAT_OBJS := arm9/source/fat/disc_io.o arm9/source/fat/gba_nds_fat.o\ +FAT_OBJS := \ + arm9/source/fat/disc_io.o \ + arm9/source/fat/gba_nds_fat.o \ arm9/source/fat/io_fcsr.o \ arm9/source/fat/io_m3cf.o \ arm9/source/fat/io_mpcf.o \ @@ -51,21 +45,65 @@ FAT_OBJS := arm9/source/fat/disc_io.o arm9/source/fat/gba_nds_fat.o\ arm9/source/fat/m3sd.o -# arm9/source/fat/io_cf_common.o arm9/source/fat/io_m3_common.o\ -# arm9/source/fat/io_sd_common.o arm9/source/fat/io_scsd_s.o \ -# arm9/source/fat/io_sc_common.o arm9/source/fat/io_sd_common.o +MODULE_OBJS := $(DATA_OBJS) $(PORT_OBJS) $(FAT_OBJS) + + +#--------------------------------------------------------------------------------- +# canned command sequence for binary data +#--------------------------------------------------------------------------------- +define bin2o + $(MKDIR) $(*D) + bin2s $< | $(AS) -mthumb -mthumb-interwork -o $(@) +endef + +define bin2h + $(MKDIR) $(*D) + echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > $@ + echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> $@ + echo "extern const u32" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> $@ +endef + +vpath %.raw $(srcdir) +vpath %.pal $(srcdir) +vpath %.bin $(srcdir) + +%.o: %.raw + $(bin2o) + +%_raw.h: %.raw + $(bin2h) + +%.o: %.pal + $(bin2o) + +%_raw.h: %.pal + $(bin2h) + +%.o: %.bin + $(bin2o) -LIBCARTRESET_OBJS := - #arm9/source/libcartreset/cartreset.o +%_raw.h: %.bin + $(bin2h) -MODULE_OBJS := +# Mark files which require the *_raw.h files manually (for now, at least) +$(MODULE)/arm9/source/dsmain.o: \ + $(MODULE)/arm9/data/icons_raw.h \ + $(MODULE)/arm9/data/keyboard_raw.h \ + $(MODULE)/arm9/data/keyboard_pal_raw.h +$(MODULE)/arm9/source/touchkeyboard.o: \ + $(MODULE)/arm9/data/keyboard_raw.h \ + $(MODULE)/arm9/data/keyboard_pal_raw.h \ + $(MODULE)/arm9/data/8x8font_tga_raw.h -# TODO: Should add more dirs to MODULE_DIRS so that "make distclean" can remove .deps dirs. MODULE_DIRS += \ - backends/platform/ds/ + backends/platform/ds/ \ + backends/platform/ds/arm7/source/ \ + backends/platform/ds/arm7/source/libcartreset/ \ + backends/platform/ds/arm9/source/ \ + backends/platform/ds/arm9/source/fat/ # We don't use the rules.mk here on purpose OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS) diff --git a/backends/platform/gp2x/build/bundle.sh b/backends/platform/gp2x/build/bundle.sh index c68c62191b..d17f8bd831 100755 --- a/backends/platform/gp2x/build/bundle.sh +++ b/backends/platform/gp2x/build/bundle.sh @@ -1,52 +1,10 @@ -#!/bin/bash +#!/bin/sh echo Quick script to make building a distribution of the GP2X port more consistent. -PATH=/opt/open2x/gcc-4.1.1-glibc-2.3.6/arm-open2x-linux/bin:$PATH -PATH=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin:$PATH -export CXX=arm-open2x-linux-g++ -export CXXFLAGS=-march=armv4t -export CPPFLAGS=-I/opt/open2x/gcc-4.1.1-glibc-2.3.6/include -export LDFLAGS=-L/opt/open2x/gcc-4.1.1-glibc-2.3.6/lib +cd ../../../.. -echo Collecting files. -mkdir "scummvm-gp2x-`date '+%Y-%m-%d'`" -mkdir "scummvm-gp2x-`date '+%Y-%m-%d'`/saves" -mkdir "scummvm-gp2x-`date '+%Y-%m-%d'`/plugins" -mkdir "scummvm-gp2x-`date '+%Y-%m-%d'`/engine-data" +echo Building ScummVM for GP2X Wiz. -echo "Please put your save games in this dir" >> "scummvm-gp2x-`date '+%Y-%m-%d'`/saves/PUT_SAVES_IN_THIS_DIR" +make gp2x-bundle -cp ./scummvm.gpe ./scummvm-gp2x-`date '+%Y-%m-%d'`/ -cp ./scummvm.png ./scummvm-gp2x-`date '+%Y-%m-%d'`/ -cp ./README-GP2X ./scummvm-gp2x-`date '+%Y-%m-%d'`/ -cp ./mmuhack.o ./scummvm-gp2x-`date '+%Y-%m-%d'`/ -cp ../../../../scummvm.gp2x ./scummvm-gp2x-`date '+%Y-%m-%d'`/ -cp ../../../../AUTHORS ./scummvm-gp2x-`date '+%Y-%m-%d'`/ -cp ../../../../README ./scummvm-gp2x-`date '+%Y-%m-%d'`/ -cp ../../../../COPYING ./scummvm-gp2x-`date '+%Y-%m-%d'`/ -cp ../../../../COPYRIGHT ./scummvm-gp2x-`date '+%Y-%m-%d'`/ -cp ../../../../NEWS ./scummvm-gp2x-`date '+%Y-%m-%d'`/ -cp ../../../../gui/themes/scummmodern.zip ./scummvm-gp2x-`date '+%Y-%m-%d'`/ -cp ../../../../backends/vkeybd/packs/vkeybd_default.zip ./scummvm-gp2x-`date '+%Y-%m-%d'`/ -cp ../../../../dists/pred.dic ./scummvm-gp2x-`date '+%Y-%m-%d'`/ -cp ../../../../dists/engine-data/* ./scummvm-gp2x-`date '+%Y-%m-%d'`/engine-data -cp ../../../../plugins/* ./scummvm-gp2x-`date '+%Y-%m-%d'`/plugins - -echo Making Stripped GPE. -arm-open2x-linux-strip ./scummvm-gp2x-`date '+%Y-%m-%d'`/scummvm.gp2x - -echo Building ZIP bundle. -if [ -f /usr/bin/zip ] - then - rm ./"scummvm-gp2x-`date '+%Y-%m-%d'`.zip" - cd "scummvm-gp2x-`date '+%Y-%m-%d'`" - zip -r -9 "../scummvm-gp2x-`date '+%Y-%m-%d'`.zip" * - echo You should have a "scummvm-gp2x-`date '+%Y-%m-%d'`.zip" for the GP2X port ready to go. - cd .. - rm -R ./"scummvm-gp2x-`date '+%Y-%m-%d'`" - else - echo - /usr/bin/zip not found, ZIP bundle not created. - echo All included files can also be found in ./"scummvm-gp2x-`date '+%Y-%m-%d'`" - echo - Please use you preferred archive tool to bundle these files. -fi diff --git a/backends/platform/gp2x/gp2x-bundle.mk b/backends/platform/gp2x/gp2x-bundle.mk new file mode 100755 index 0000000000..c6fb72c1c3 --- /dev/null +++ b/backends/platform/gp2x/gp2x-bundle.mk @@ -0,0 +1,60 @@ +# Special target to create bundles for the GP2X. + +bundle_name = release/scummvm-gp2x + +gp2x-bundle: $(EXECUTABLE) + $(MKDIR) "$(bundle_name)" + $(MKDIR) "$(bundle_name)/saves" + $(MKDIR) "$(bundle_name)/engine-data" + + echo "Please put your save games in this dir" >> "$(bundle_name)/saves/PUT_SAVES_IN_THIS_DIR" + + $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.gpe $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.png $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gp2x/build/README-GP2X $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gp2x/build/mmuhack.o $(bundle_name)/ + + $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/ + $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/ + $(INSTALL) -c -m 644 $(DIST_FILES_ENGINEDATA) $(bundle_name)/engine-data + $(CP) $(srcdir)/backends/vkeybd/packs/vkeybd_default.zip $(bundle_name)/ + + $(STRIP) $(EXECUTABLE) -o $(bundle_name)/$(EXECUTABLE) + +ifdef DYNAMIC_MODULES + $(INSTALL) -d "$(bundle_name)/plugins" + $(INSTALL) -c -m 644 $(PLUGINS) "$(bundle_name)/plugins" + $(STRIP) $(bundle_name)/plugins/* +endif + + tar -C $(bundle_name) -cvjf $(bundle_name).tar.bz2 . + rm -R ./$(bundle_name) + +gp2x-bundle-debug: $(EXECUTABLE) + $(MKDIR) "$(bundle_name)" + $(MKDIR) "$(bundle_name)/saves" + $(MKDIR) "$(bundle_name)/engine-data" + + echo "Please put your save games in this dir" >> "$(bundle_name)/saves/PUT_SAVES_IN_THIS_DIR" + + $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.gpe $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gp2x/build/scummvm.png $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gp2x/build/README-GP2X $(bundle_name)/ + $(CP) $(srcdir)/backends/platform/gp2x/build/mmuhack.o $(bundle_name)/ + + $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/ + $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/ + $(INSTALL) -c -m 644 $(DIST_FILES_ENGINEDATA) $(bundle_name)/engine-data + $(CP) $(srcdir)/backends/vkeybd/packs/vkeybd_default.zip $(bundle_name)/ + + $(INSTALL) -c -m 777 $(srcdir)/$(EXECUTABLE) $(bundle_name)/$(EXECUTABLE) + +ifdef DYNAMIC_MODULES + $(INSTALL) -d "$(bundle_name)/scummvm/plugins" + $(INSTALL) -c -m 644 $(PLUGINS) "$(bundle_name)/scummvm/plugins" +endif + + tar -C $(bundle_name) -cvjf $(bundle_name)-debug.tar.bz2 . + rm -R ./$(bundle_name) + +.PHONY: gp2x-bundle gp2x-bundle-debug diff --git a/backends/platform/gp2xwiz/build/bundle-debug.sh b/backends/platform/gp2xwiz/build/bundle-debug.sh new file mode 100755 index 0000000000..cd5145b31d --- /dev/null +++ b/backends/platform/gp2xwiz/build/bundle-debug.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +echo Quick script to make building a distribution of the GP2X Wiz backend more consistent. + +cd ../../../.. + +echo Building ScummVM for GP2X Wiz. + +make gp2xwiz-bundle-debug diff --git a/backends/platform/gp2xwiz/build/bundle.sh b/backends/platform/gp2xwiz/build/bundle.sh index 065bd7a685..579e2dc77b 100755 --- a/backends/platform/gp2xwiz/build/bundle.sh +++ b/backends/platform/gp2xwiz/build/bundle.sh @@ -2,56 +2,8 @@ echo Quick script to make building a distribution of the GP2X Wiz backend more consistent. -echo Collecting files. -mkdir "scummvm-wiz-`date '+%Y-%m-%d'`" -mkdir "scummvm-wiz-`date '+%Y-%m-%d'`/scummvm" -mkdir "scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/saves" -mkdir "scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/plugins" -mkdir "scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/engine-data" -mkdir "scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/lib" +cd ../../../.. +echo Building ScummVM for GP2X Wiz. -echo "Please put your save games in this dir" >> "scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/saves/PUT_SAVES_IN_THIS_DIR" - -cp ./scummvm.gpe ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/ -cp ./scummvm.png ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/ -cp ./README-GP2XWIZ ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/ -cp ./scummvm.ini ./scummvm-wiz-`date '+%Y-%m-%d'`/ -cp ../../../../scummvm.wiz ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/ -cp ../../../../AUTHORS ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/ -cp ../../../../README ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/ -cp ../../../../COPYING ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/ -cp ../../../../COPYRIGHT ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/ -cp ../../../../NEWS ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/ -cp ../../../../gui/themes/scummmodern.zip ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/ -cp ../../../../backends/vkeybd/packs/vkeybd_default.zip ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/ -cp ../../../../dists/pred.dic ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/ -cp ../../../../dists/engine-data/* ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/engine-data -cp ../../../../plugins/* ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/plugins - -# Copy over dynamic libs needed by the app (as the ones in the default filesystem are broken). -f=`which arm-open2x-linux-g++` -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/libvorbisidec.so.1.0.2 ./scummvm-wiz-`date '+%Y-%m-%d'`/scummvm/lib/libvorbisidec.so.1 - -echo Making Stripped Binary. -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. -if [ -f /usr/bin/zip ] - then - rm ./"scummvm-wiz-`date '+%Y-%m-%d'`.zip" - cd "scummvm-wiz-`date '+%Y-%m-%d'`" - zip -r -9 "../scummvm-wiz-`date '+%Y-%m-%d'`.zip" * - echo You should have a "scummvm-wiz-`date '+%Y-%m-%d'`.zip" for the GP2X Wiz backend ready to go. - cd .. - rm -R ./"scummvm-wiz-`date '+%Y-%m-%d'`" - else - echo - /usr/bin/zip not found, ZIP bundle not created. - echo All included files can also be found in ./"scummvm-wiz-`date '+%Y-%m-%d'`" - echo - Please use you preferred archive tool to bundle these files. -fi +make gp2xwiz-bundle diff --git a/backends/platform/gp2xwiz/build/scummvm-gdb.gpe b/backends/platform/gp2xwiz/build/scummvm-gdb.gpe new file mode 100755 index 0000000000..64b6c8b974 --- /dev/null +++ b/backends/platform/gp2xwiz/build/scummvm-gdb.gpe @@ -0,0 +1,16 @@ +#!/bin/sh + +# Export the location of any libs ScummVM depends on +# (to avoid installing to the NAND and overwriting the broken ones there). +export LD_LIBRARY_PATH=`pwd`/lib:$LD_LIBRARY_PATH + +# Run ScummVM via GDB (so make sure you have a terminal open or serial). +# Oh, and GDB installed of course ;) +gdb --args ./scummvm.wiz --fullscreen --gfx-mode=1x --config=$(pwd)/.scummvmrc + +# Sync the SD card to check that everything is written. +sync + +# Return to the GPH menu screen +cd /usr/gp2x +exec /usr/gp2x/gp2xmenu diff --git a/backends/platform/gp2xwiz/gp2xwiz-bundle.mk b/backends/platform/gp2xwiz/gp2xwiz-bundle.mk new file mode 100755 index 0000000000..fa5a247865 --- /dev/null +++ b/backends/platform/gp2xwiz/gp2xwiz-bundle.mk @@ -0,0 +1,73 @@ +# Special target to create bundles for the GP2X Wiz. + +#bundle_name = release/scummvm-wiz-`date '+%Y-%m-%d'` +bundle_name = release/scummvm-gp2xwiz +f=$(shell which $(STRIP)) +libloc = $(shell dirname $(f)) + +gp2xwiz-bundle: $(EXECUTABLE) + $(MKDIR) "$(bundle_name)" + $(MKDIR) "$(bundle_name)/scummvm" + $(MKDIR) "$(bundle_name)/scummvm/saves" + $(MKDIR) "$(bundle_name)/scummvm/engine-data" + $(MKDIR) "$(bundle_name)/scummvm/lib" + + echo "Please put your save games in this dir" >> "$(bundle_name)/scummvm/saves/PUT_SAVES_IN_THIS_DIR" + + $(CP) $(srcdir)/backends/platform/gp2xwiz/build/scummvm.gpe $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gp2xwiz/build/scummvm.png $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gp2xwiz/build/README-GP2XWIZ $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gp2xwiz/build/scummvm.ini $(bundle_name)/ + + $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/ + $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/scummvm/ + $(INSTALL) -c -m 644 $(DIST_FILES_ENGINEDATA) $(bundle_name)/scummvm/engine-data + $(CP) $(srcdir)/backends/vkeybd/packs/vkeybd_default.zip $(bundle_name)/scummvm/ + + $(STRIP) $(EXECUTABLE) -o $(bundle_name)/scummvm/$(EXECUTABLE) + +ifdef DYNAMIC_MODULES + $(INSTALL) -d "$(bundle_name)/scummvm/plugins" + $(INSTALL) -c -m 644 $(PLUGINS) "$(bundle_name)/scummvm/plugins" + $(STRIP) $(bundle_name)/scummvm/plugins/* +endif + + $(CP) $(libloc)/../lib/libz.so.1.2.3 $(bundle_name)/scummvm/lib/libz.so.1 + $(CP) $(libloc)/../lib/libvorbisidec.so.1.0.2 $(bundle_name)/scummvm/lib/libvorbisidec.so.1 + + tar -C $(bundle_name) -cvjf $(bundle_name).tar.bz2 . + rm -R ./$(bundle_name) + +gp2xwiz-bundle-debug: $(EXECUTABLE) + $(MKDIR) "$(bundle_name)" + $(MKDIR) "$(bundle_name)/scummvm" + $(MKDIR) "$(bundle_name)/scummvm/saves" + $(MKDIR) "$(bundle_name)/scummvm/engine-data" + $(MKDIR) "$(bundle_name)/scummvm/lib" + + echo "Please put your save games in this dir" >> "$(bundle_name)/scummvm/saves/PUT_SAVES_IN_THIS_DIR" + + $(CP) $(srcdir)/backends/platform/gp2xwiz/build/scummvm-gdb.gpe $(bundle_name)/scummvm/scummvm.gpe + $(CP) $(srcdir)/backends/platform/gp2xwiz/build/scummvm.png $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gp2xwiz/build/README-GP2XWIZ $(bundle_name)/scummvm/ + $(CP) $(srcdir)/backends/platform/gp2xwiz/build/scummvm.ini $(bundle_name)/ + + $(INSTALL) -c -m 644 $(DIST_FILES_DOCS) $(bundle_name)/scummvm/ + $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(bundle_name)/scummvm/ + $(INSTALL) -c -m 644 $(DIST_FILES_ENGINEDATA) $(bundle_name)/scummvm/engine-data + $(CP) $(srcdir)/backends/vkeybd/packs/vkeybd_default.zip $(bundle_name)/scummvm/ + + $(INSTALL) -c -m 777 $(srcdir)/$(EXECUTABLE) $(bundle_name)/scummvm/$(EXECUTABLE) + +ifdef DYNAMIC_MODULES + $(INSTALL) -d "$(bundle_name)/scummvm/plugins" + $(INSTALL) -c -m 644 $(PLUGINS) "$(bundle_name)/scummvm/plugins" +endif + + $(CP) $(libloc)/../lib/libz.so.1.2.3 $(bundle_name)/scummvm/lib/libz.so.1 + $(CP) $(libloc)/../lib/libvorbisidec.so.1.0.2 $(bundle_name)/scummvm/lib/libvorbisidec.so.1 + + tar -C $(bundle_name) -cvjf $(bundle_name)-debug.tar.bz2 . + rm -R ./$(bundle_name) + +.PHONY: gp2xwiz-bundle gp2xwiz-bundle-debug diff --git a/backends/platform/iphone/osys_events.cpp b/backends/platform/iphone/osys_events.cpp index 72408be89a..c1c7ffdc0c 100644 --- a/backends/platform/iphone/osys_events.cpp +++ b/backends/platform/iphone/osys_events.cpp @@ -24,6 +24,7 @@ */ #include "gui/message.h" +#include "common/translation.h" #include "osys_main.h" @@ -335,9 +336,9 @@ bool OSystem_IPHONE::handleEvent_mouseSecondDragged(Common::Event &event, int x, _touchpadModeEnabled = !_touchpadModeEnabled; const char *dialogMsg; if (_touchpadModeEnabled) - dialogMsg = "Touchpad mode enabled."; + dialogMsg = _("Touchpad mode enabled."); else - dialogMsg = "Touchpad mode disabled."; + dialogMsg = _("Touchpad mode disabled."); GUI::TimedMessageDialog dialog(dialogMsg, 1500); dialog.runModal(); return false; diff --git a/backends/platform/psp/Makefile b/backends/platform/psp/Makefile index 7f8bb63b0a..fed558eaad 100644 --- a/backends/platform/psp/Makefile +++ b/backends/platform/psp/Makefile @@ -124,17 +124,13 @@ CXXFLAGS += -pg -g LDFLAGS += -pg endif -# SDL Libs and Flags -SDLFLAGS := $(shell $(PSPBIN)/sdl-config --cflags) -SDLLIBS := $(shell $(PSPBIN)/sdl-config --libs) # PSP LIBS PSPLIBS = -lpspprof -lpspvfpu -lpspdebug -lpspgu -lpspge -lpspdisplay -lpspctrl -lpspsdk \ -lpsputility -lpspuser -lpsppower -lpsphprm -lpspsdk -lpsprtc -lpspaudio -lpspaudiocodec \ -lpspkernel # Add in PSPSDK includes and libraries. -CXXFLAGS += $(SDLFLAGS) -LIBS += -lpng -lSDL -lz $(findstring -lGL,$(SDLLIBS)) -lstdc++ -lc -lm $(filter -L%,$(SDLLIBS)) $(PSPLIBS) +LIBS += -lpng -lz -lstdc++ -lc -lm $(PSPLIBS) OBJS := powerman.o \ psp_main.o \ @@ -151,6 +147,7 @@ OBJS := powerman.o \ pspkeyboard.o \ audio.o \ thread.o \ + rtc.o \ mp3.o # Include common Scummvm makefile diff --git a/backends/platform/psp/README.PSP b/backends/platform/psp/README.PSP index 45f31483f7..f4d5bae6d6 100644 --- a/backends/platform/psp/README.PSP +++ b/backends/platform/psp/README.PSP @@ -99,8 +99,6 @@ To build ScummVM for PSP you need: Note: This usually gets installed by the PSP toolchain, so you don't have to do it manually. -- SDL (svn co svn://svn.pspdev.org/psp/trunk/SDL) - - zlib (svn co svn://svn.pspdev.org/psp/trunk/zlib) - libPNG (svn co svn://svn.pspdev.org/psp/trunk/libpng) diff --git a/backends/platform/psp/README.PSP.in b/backends/platform/psp/README.PSP.in index d9f75974f1..2d53fd3b47 100644 --- a/backends/platform/psp/README.PSP.in +++ b/backends/platform/psp/README.PSP.in @@ -99,8 +99,6 @@ To build ScummVM for PSP you need: Note: This usually gets installed by the PSP toolchain, so you don't have to do it manually. -- SDL (svn co svn://svn.pspdev.org/psp/trunk/SDL) - - zlib (svn co svn://svn.pspdev.org/psp/trunk/zlib) - libPNG (svn co svn://svn.pspdev.org/psp/trunk/libpng) diff --git a/backends/platform/psp/display_manager.cpp b/backends/platform/psp/display_manager.cpp index c2f21e084b..a9f33f6091 100644 --- a/backends/platform/psp/display_manager.cpp +++ b/backends/platform/psp/display_manager.cpp @@ -311,27 +311,29 @@ void DisplayManager::calculateScaleParams() { } } -void DisplayManager::renderAll() { +// return true if we really rendered or no dirty. False otherwise +bool DisplayManager::renderAll() { DEBUG_ENTER_FUNC(); #ifdef USE_DISPLAY_CALLBACK if (!_masterGuRenderer.isRenderFinished()) { PSP_DEBUG_PRINT("Callback render not finished.\n"); - return; + return false; // didn't render } #endif /* USE_DISPLAY_CALLBACK */ - if (!isTimeToUpdate()) - return; - + // This is cheaper than checking time, so we do it first if (!_screen->isDirty() && (!_overlay->isDirty()) && (!_cursor->isDirty()) && (!_keyboard->isDirty())) { PSP_DEBUG_PRINT("Nothing dirty\n"); - return; + return true; // nothing to render } + if (!isTimeToUpdate()) + return false; // didn't render + PSP_DEBUG_PRINT("screen[%s], overlay[%s], cursor[%s], keyboard[%s]\n", _screen->isDirty() ? "true" : "false", _overlay->isDirty() ? "true" : "false", @@ -361,6 +363,8 @@ void DisplayManager::renderAll() { _keyboard->setClean(); _masterGuRenderer.guPostRender(); + + return true; // rendered successfully } inline bool DisplayManager::isTimeToUpdate() { @@ -375,7 +379,7 @@ inline bool DisplayManager::isTimeToUpdate() { return true; } -Common::List<Graphics::PixelFormat> DisplayManager::getSupportedPixelFormats() { +Common::List<Graphics::PixelFormat> DisplayManager::getSupportedPixelFormats() const { Common::List<Graphics::PixelFormat> list; // In order of preference diff --git a/backends/platform/psp/display_manager.h b/backends/platform/psp/display_manager.h index 5864f39b36..dbbdf2022c 100644 --- a/backends/platform/psp/display_manager.h +++ b/backends/platform/psp/display_manager.h @@ -40,12 +40,12 @@ public: void setupCallbackThread(); private: static uint32 _displayList[]; - uint32 _lastRenderTime; // For measuring rendering + uint32 _lastRenderTime; // For measuring rendering time void guProgramDisplayBufferSizes(); static int guCallbackThread(SceSize, void *); // for the graphics callbacks static int guCallback(int, int, void *__this); - bool _renderFinished; - int _callbackId; + bool _renderFinished; // for sync with render callback + int _callbackId; // to keep track of render callback }; class Screen; @@ -68,7 +68,7 @@ public: ~DisplayManager(); void init(); - void renderAll(); + bool renderAll(); // return true if rendered or nothing dirty. False otherwise bool setGraphicsMode(int mode); bool setGraphicsMode(const char *name); int getGraphicsMode() const { return _graphicsMode; } @@ -83,12 +83,12 @@ public: void setSizeAndPixelFormat(uint width, uint height, const Graphics::PixelFormat *format); // Getters - float getScaleX() { return _displayParams.scaleX; } - float getScaleY() { return _displayParams.scaleY; } - uint32 getOutputWidth() { return _displayParams.screenOutput.width; } - uint32 getOutputHeight() { return _displayParams.screenOutput.height; } - uint32 getOutputBitsPerPixel() { return _displayParams.outputBitsPerPixel; } - Common::List<Graphics::PixelFormat> getSupportedPixelFormats(); + float getScaleX() const { return _displayParams.scaleX; } + float getScaleY() const { return _displayParams.scaleY; } + uint32 getOutputWidth() const { return _displayParams.screenOutput.width; } + uint32 getOutputHeight() const { return _displayParams.screenOutput.height; } + uint32 getOutputBitsPerPixel() const { return _displayParams.outputBitsPerPixel; } + Common::List<Graphics::PixelFormat> getSupportedPixelFormats() const; private: struct GlobalDisplayParams { diff --git a/backends/platform/psp/module.mk b/backends/platform/psp/module.mk index 99170ce7fb..e9c896acfd 100644 --- a/backends/platform/psp/module.mk +++ b/backends/platform/psp/module.mk @@ -15,6 +15,7 @@ MODULE_OBJS := powerman.o \ pspkeyboard.o \ audio.o \ thread.o \ + rtc.o \ mp3.o MODULE_DIRS += \ diff --git a/backends/platform/psp/mp3.cpp b/backends/platform/psp/mp3.cpp index 972c5a8ba8..e25891396b 100644 --- a/backends/platform/psp/mp3.cpp +++ b/backends/platform/psp/mp3.cpp @@ -85,13 +85,13 @@ bool Mp3PspStream::initDecoder() { } } else { if (sceUtilityLoadAvModule(PSP_AV_MODULE_AVCODEC) < 0) { - PSP_ERROR("failed to load AVCODEC module.\n"); + PSP_ERROR("failed to load AVCODEC module. ME cannot start.\n"); _decoderFail = true; return false; } } - PSP_INFO_PRINT("Using PSP's ME for MP3\n"); // important to know this is happening + PSP_DEBUG_PRINT("Using PSP's ME for MP3\n"); // important to know this is happening _decoderInit = true; return true; @@ -319,7 +319,7 @@ void Mp3PspStream::decodeMP3Data() { // 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); + PSP_INFO_PRINT("failed to decode MP3 data in ME. sceAudiocodecDecode returned 0x%x\n", ret); // handle error here } diff --git a/backends/platform/psp/mp3.h b/backends/platform/psp/mp3.h index f8802f930c..029b3e498c 100644 --- a/backends/platform/psp/mp3.h +++ b/backends/platform/psp/mp3.h @@ -110,7 +110,7 @@ public: bool endOfData() const { return _state == MP3_STATE_EOS; } bool isStereo() const { return MAD_NCHANNELS(&_header) == 2; } - int getRate() const { return _header.samplerate; } + int getRate() const { return _sampleRate; } bool seek(const Timestamp &where); Timestamp getLength() const { return _length; } diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp index 2043a4bef2..b09d9c0c00 100644 --- a/backends/platform/psp/osys_psp.cpp +++ b/backends/platform/psp/osys_psp.cpp @@ -37,6 +37,7 @@ #include "backends/platform/psp/psppixelformat.h" #include "backends/platform/psp/osys_psp.h" #include "backends/platform/psp/powerman.h" +#include "backends/platform/psp/rtc.h" #include "backends/saves/psp/psp-saves.h" #include "backends/timer/default/default-timer.h" @@ -48,8 +49,6 @@ #include "backends/platform/psp/trace.h" -#define USE_PSP_AUDIO - #define SAMPLES_PER_SEC 44100 static int timer_handler(int t) { @@ -58,14 +57,6 @@ static int timer_handler(int t) { return t; } -void OSystem_PSP::initSDL() { -#ifdef USE_PSP_AUDIO - SDL_Init(0); -#else - SDL_Init(SDL_INIT_AUDIO); -#endif -} - OSystem_PSP::~OSystem_PSP() {} #define PSP_SCREEN_WIDTH 480 @@ -74,6 +65,9 @@ OSystem_PSP::~OSystem_PSP() {} void OSystem_PSP::initBackend() { DEBUG_ENTER_FUNC(); + // Instantiate real time clock + PspRtc::instance(); + _cursor.enableCursorPalette(false); _cursor.setXY(PSP_SCREEN_WIDTH >> 1, PSP_SCREEN_HEIGHT >> 1); // Mouse in the middle of the screen @@ -89,8 +83,6 @@ void OSystem_PSP::initBackend() { _inputHandler.setKeyboard(&_keyboard); _inputHandler.init(); - initSDL(); - _savefile = new PSPSaveFileManager; _timer = new DefaultTimerManager(); @@ -127,11 +119,13 @@ int OSystem_PSP::getDefaultGraphicsMode() const { bool OSystem_PSP::setGraphicsMode(int mode) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; return _displayManager.setGraphicsMode(mode); } bool OSystem_PSP::setGraphicsMode(const char *name) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; return _displayManager.setGraphicsMode(name); } @@ -146,7 +140,7 @@ Graphics::PixelFormat OSystem_PSP::getScreenFormat() const { return _screen.getScummvmPixelFormat(); } -Common::List<Graphics::PixelFormat> OSystem_PSP::getSupportedFormats() { +Common::List<Graphics::PixelFormat> OSystem_PSP::getSupportedFormats() const { return _displayManager.getSupportedPixelFormats(); } @@ -154,6 +148,7 @@ Common::List<Graphics::PixelFormat> OSystem_PSP::getSupportedFormats() { void OSystem_PSP::initSize(uint width, uint height, const Graphics::PixelFormat *format) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _displayManager.setSizeAndPixelFormat(width, height, format); _cursor.setVisible(false); @@ -172,6 +167,7 @@ int16 OSystem_PSP::getHeight() { void OSystem_PSP::setPalette(const byte *colors, uint start, uint num) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _screen.setPartialPalette(colors, start, num); _cursor.setScreenPalette(colors, start, num); _cursor.clearKeyColor(); @@ -179,6 +175,7 @@ void OSystem_PSP::setPalette(const byte *colors, uint start, uint num) { void OSystem_PSP::setCursorPalette(const byte *colors, uint start, uint num) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _cursor.setCursorPalette(colors, start, num); _cursor.enableCursorPalette(true); _cursor.clearKeyColor(); // Do we need this? @@ -186,37 +183,43 @@ void OSystem_PSP::setCursorPalette(const byte *colors, uint start, uint num) { void OSystem_PSP::disableCursorPalette(bool disable) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _cursor.enableCursorPalette(!disable); } void OSystem_PSP::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _screen.copyFromRect(buf, pitch, x, y, w, h); } Graphics::Surface *OSystem_PSP::lockScreen() { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; return _screen.lockAndGetForEditing(); } void OSystem_PSP::unlockScreen() { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; // The screen is always completely updated anyway, so we don't have to force a full update here. _screen.unlock(); } void OSystem_PSP::updateScreen() { DEBUG_ENTER_FUNC(); - _displayManager.renderAll(); + _pendingUpdate = !_displayManager.renderAll(); // if we didn't update, we have a pending update } void OSystem_PSP::setShakePos(int shakeOffset) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _screen.setShakePos(shakeOffset); } void OSystem_PSP::showOverlay() { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _overlay.setVisible(true); _cursor.setLimits(_overlay.getWidth(), _overlay.getHeight()); _cursor.useGlobalScaler(false); // mouse with overlay is 1:1 @@ -224,6 +227,7 @@ void OSystem_PSP::showOverlay() { void OSystem_PSP::hideOverlay() { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _overlay.setVisible(false); _cursor.setLimits(_screen.getWidth(), _screen.getHeight()); _cursor.useGlobalScaler(true); // mouse needs to be scaled with screen @@ -231,6 +235,7 @@ void OSystem_PSP::hideOverlay() { void OSystem_PSP::clearOverlay() { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _overlay.clearBuffer(); } @@ -241,6 +246,7 @@ void OSystem_PSP::grabOverlay(OverlayColor *buf, int pitch) { void OSystem_PSP::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _overlay.copyFromRect(buf, pitch, x, y, w, h); } @@ -259,6 +265,8 @@ void OSystem_PSP::grabPalette(byte *colors, uint start, uint num) { bool OSystem_PSP::showMouse(bool v) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; + PSP_DEBUG_PRINT("%s\n", v ? "true" : "false"); bool last = _cursor.isVisible(); _cursor.setVisible(v); @@ -268,11 +276,14 @@ bool OSystem_PSP::showMouse(bool v) { void OSystem_PSP::warpMouse(int x, int y) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; _cursor.setXY(x, y); } void OSystem_PSP::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { DEBUG_ENTER_FUNC(); + _pendingUpdate = false; + PSP_DEBUG_PRINT("pbuf[%p], w[%u], h[%u], hotspot:X[%d], Y[%d], keycolor[%d], scale[%d], pformat[%p]\n", buf, w, h, hotspotX, hotspotY, keycolor, cursorTargetScale, format); if (format) { PSP_DEBUG_PRINT("format: bpp[%d], rLoss[%d], gLoss[%d], bLoss[%d], aLoss[%d], rShift[%d], gShift[%d], bShift[%d], aShift[%d]\n", format->bytesPerPixel, format->rLoss, format->gLoss, format->bLoss, format->aLoss, format->rShift, format->gShift, format->bShift, format->aShift); @@ -292,14 +303,28 @@ bool OSystem_PSP::pollEvent(Common::Event &event) { // Pausing the engine is a necessary fix for games that use the timer for music synchronization // recovering many hours later causes the game to crash. We're polling without mutexes since it's not critical to // get it right now. - PowerMan.pollPauseEngine(); + // A hack: + // Check if we have a pending update that we missed for some reason (FPS throttling for example) + // Time between event polls is usually 5-10ms, so waiting for 4 calls before checking to update the screen should be fine + if (_pendingUpdate) { + _pendingUpdateCounter++; + + if (_pendingUpdateCounter >= 4) { + PSP_DEBUG_PRINT("servicing pending update\n"); + updateScreen(); + if (!_pendingUpdate) // we handled the update + _pendingUpdateCounter = 0; + } + } else + _pendingUpdateCounter = 0; // reset the counter, no pending + return _inputHandler.getAllInputs(event); } uint32 OSystem_PSP::getMillis() { - return _pspRtc.getMillis(); + return PspRtc::instance().getMillis(); } void OSystem_PSP::delayMillis(uint msecs) { @@ -313,19 +338,19 @@ void OSystem_PSP::setTimerCallback(TimerProc callback, int interval) { } OSystem::MutexRef OSystem_PSP::createMutex(void) { - return (MutexRef)SDL_CreateMutex(); + return (MutexRef) new PspMutex(true); // start with a full mutex } void OSystem_PSP::lockMutex(MutexRef mutex) { - SDL_mutexP((SDL_mutex *)mutex); + ((PspMutex *)mutex)->lock(); } void OSystem_PSP::unlockMutex(MutexRef mutex) { - SDL_mutexV((SDL_mutex *)mutex); + ((PspMutex *)mutex)->unlock(); } void OSystem_PSP::deleteMutex(MutexRef mutex) { - SDL_DestroyMutex((SDL_mutex *)mutex); + delete (PspMutex *)mutex; } void OSystem_PSP::mixCallback(void *sys, byte *samples, int len) { @@ -355,7 +380,6 @@ void OSystem_PSP::setupMixer(void) { assert(!_mixer); -#ifdef USE_PSP_AUDIO if (!_audio.open(samplesPerSec, 2, samples, mixCallback, this)) { PSP_ERROR("failed to open audio\n"); return; @@ -365,46 +389,10 @@ void OSystem_PSP::setupMixer(void) { assert(_mixer); _mixer->setReady(true); _audio.unpause(); -#else - SDL_AudioSpec obtained; - SDL_AudioSpec desired; - - memset(&desired, 0, sizeof(desired)); - desired.freq = samplesPerSec; - desired.format = AUDIO_S16SYS; - desired.channels = 2; - desired.samples = samples; - desired.callback = mixCallback; - desired.userdata = this; - - if (SDL_OpenAudio(&desired, &obtained) != 0) { - warning("Could not open audio: %s", SDL_GetError()); - _mixer = new Audio::MixerImpl(this, samplesPerSec); - assert(_mixer); - _mixer->setReady(false); - } else { - // Note: This should be the obtained output rate, but it seems that at - // least on some platforms SDL will lie and claim it did get the rate - // even if it didn't. Probably only happens for "weird" rates, though. - samplesPerSec = obtained.freq; - - // Create the mixer instance and start the sound processing - _mixer = new Audio::MixerImpl(this, samplesPerSec); - assert(_mixer); - _mixer->setReady(true); - - SDL_PauseAudio(0); - } -#endif /* USE_PSP_AUDIO */ } void OSystem_PSP::quit() { -#ifdef USE_PSP_AUDIO _audio.close(); -#else - SDL_CloseAudio(); -#endif - SDL_Quit(); sceKernelExitGame(); } diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h index a6c84ba39a..5721296c94 100644 --- a/backends/platform/psp/osys_psp.h +++ b/backends/platform/psp/osys_psp.h @@ -42,14 +42,14 @@ #include "backends/timer/psp/timer.h" #include "backends/platform/psp/thread.h" -#include <SDL.h> - class OSystem_PSP : public BaseBackend { private: Common::SaveFileManager *_savefile; Audio::MixerImpl *_mixer; Common::TimerManager *_timer; + bool _pendingUpdate; // save an update we couldn't perform + uint32 _pendingUpdateCounter; // prevent checking for pending update too often, in a cheap way // All needed sub-members Screen _screen; @@ -60,12 +60,9 @@ private: InputHandler _inputHandler; PspAudio _audio; PspTimer _pspTimer; - PspRtc _pspRtc; - - void initSDL(); public: - OSystem_PSP() : _savefile(0), _mixer(0), _timer(0) {} + OSystem_PSP() : _savefile(0), _mixer(0), _timer(0), _pendingUpdate(false), _pendingUpdateCounter(0) {} ~OSystem_PSP(); static OSystem *instance(); @@ -85,7 +82,7 @@ public: int getGraphicsMode() const; #ifdef USE_RGB_COLOR virtual Graphics::PixelFormat getScreenFormat() const; - virtual Common::List<Graphics::PixelFormat> getSupportedFormats(); + virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const; #endif // Screen size diff --git a/backends/platform/psp/powerman.cpp b/backends/platform/psp/powerman.cpp index df8da12f6d..eaadad16c5 100644 --- a/backends/platform/psp/powerman.cpp +++ b/backends/platform/psp/powerman.cpp @@ -23,16 +23,16 @@ * */ -//#define __PSP_DEBUG_FUNCS__ /* can put this locally too */ -//#define __PSP_DEBUG_PRINT__ -#include "backends/platform/psp/trace.h" - #include <psppower.h> #include <pspthreadman.h> #include "backends/platform/psp/powerman.h" #include "engine.h" +//#define __PSP_DEBUG_FUNCS__ /* can put this locally too */ +//#define __PSP_DEBUG_PRINT__ +#include "backends/platform/psp/trace.h" + DECLARE_SINGLETON(PowerManager) // Function to debug the Power Manager (we have no output to screen) @@ -47,68 +47,30 @@ inline void PowerManager::debugPM() { * Constructor * ********************************************/ -PowerManager::PowerManager() { - DEBUG_ENTER_FUNC(); - - _flagMutex = NULL; /* Init mutex handle */ - _listMutex = NULL; /* Init mutex handle */ - _condSuspendable = NULL; /* Init condition variable */ - _condPM = NULL; - - _condSuspendable = SDL_CreateCond(); - if (_condSuspendable <= 0) { - PSP_ERROR("Couldn't create Suspendable condition variable\n"); - } - - _condPM = SDL_CreateCond(); - if (_condPM <= 0) { - PSP_ERROR("Couldn't create PM condition variable\n"); - } - - _flagMutex = SDL_CreateMutex(); - if (_flagMutex <= 0) { - PSP_ERROR("Couldn't create flag Mutex\n"); - } - - _listMutex = SDL_CreateMutex(); - if (_listMutex <= 0) { - PSP_ERROR("Couldn't create list Mutex\n"); - } - - _suspendFlag = false; - _criticalCounter = 0; // How many are in the critical section - _pauseFlag = 0; - _pauseFlagOld = 0; - _pauseClientState = 0; - _listCounter = 0; - PMStatusSet(kInitDone); - _error = 0; -} +PowerManager::PowerManager() : _pauseFlag(false), _pauseFlagOld(false), _pauseClientState(UNPAUSED), + _suspendFlag(false), _flagMutex(true), _listMutex(true), + _criticalCounter(0), _listCounter(0), _error(0), _PMStatus(kInitDone) {} /******************************************* * * Function to register to be notified when suspend/resume time comes * ********************************************/ -int PowerManager::registerSuspend(Suspendable *item) { +bool PowerManager::registerForSuspend(Suspendable *item) { DEBUG_ENTER_FUNC(); // Register in list debugPM(); - if (SDL_mutexP(_listMutex) != 0) { - PSP_ERROR("Couldn't lock _listMutex[%p]\n", _listMutex); - } + _listMutex.lock(); _suspendList.push_front(item); _listCounter++; - if (SDL_mutexV(_listMutex) != 0) { - PSP_ERROR("Couldn't unlock _listMutex[%p]\n", _listMutex); - } + _listMutex.unlock(); debugPM(); - return 0; + return true; } /******************************************* @@ -116,26 +78,20 @@ int PowerManager::registerSuspend(Suspendable *item) { * Function to unregister to be notified when suspend/resume time comes * ********************************************/ -int PowerManager::unregisterSuspend(Suspendable *item) { +bool PowerManager::unregisterForSuspend(Suspendable *item) { DEBUG_ENTER_FUNC(); debugPM(); // Unregister from stream list - if (SDL_mutexP(_listMutex) != 0) { - PSP_ERROR("Couldn't unlock _listMutex[%p]\n", _listMutex); - } - + _listMutex.lock(); + _suspendList.remove(item); _listCounter--; - if (SDL_mutexV(_listMutex) != 0) { - PSP_ERROR("Couldn't unlock _listMutex[%p]\n", _listMutex); - } + _listMutex.unlock(); - PSP_DEBUG_PRINT("Out of unregisterSuspend\n"); debugPM(); - - return 0; + return true; } /******************************************* @@ -144,21 +100,7 @@ int PowerManager::unregisterSuspend(Suspendable *item) { * ********************************************/ PowerManager::~PowerManager() { - DEBUG_ENTER_FUNC(); - - PMStatusSet(kDestroyPM); - - SDL_DestroyCond(_condSuspendable); - _condSuspendable = 0; - - SDL_DestroyCond(_condPM); - _condPM = 0; - - SDL_DestroyMutex(_flagMutex); - _flagMutex = 0; - - SDL_DestroyMutex(_listMutex); - _listMutex = 0; + _PMStatus = kDestroyPM; } /******************************************* @@ -171,114 +113,92 @@ PowerManager::~PowerManager() { * ********************************************/ void PowerManager::pollPauseEngine() { - + DEBUG_ENTER_FUNC(); + + bool pause = _pauseFlag; // We copy so as not to have multiple values - if ((pause != _pauseFlagOld) && g_engine) { // Check to see if we have an engine - if (pause && _pauseClientState == PowerManager::Unpaused) { - _pauseClientState = PowerManager::Pausing; // Tell PM we're in the middle of pausing - g_engine->pauseEngine(true); - PSP_DEBUG_PRINT_FUNC("Pausing engine\n"); - _pauseClientState = PowerManager::Paused; // Tell PM we're done pausing - } else if (!pause && _pauseClientState == PowerManager::Paused) { - g_engine->pauseEngine(false); - PSP_DEBUG_PRINT_FUNC("Unpausing for resume\n"); - _pauseClientState = PowerManager::Unpaused; // Tell PM we're in the middle of pausing + if (pause != _pauseFlagOld) { + if (g_engine) { // Check to see if we have an engine + if (pause && _pauseClientState == UNPAUSED) { + _pauseClientState = PAUSING; // Tell PM we're in the middle of pausing + g_engine->pauseEngine(true); + PSP_DEBUG_PRINT_FUNC("Pausing engine\n"); + _pauseClientState = PAUSED; // Tell PM we're done pausing + } else if (!pause && _pauseClientState == PAUSED) { + g_engine->pauseEngine(false); + PSP_DEBUG_PRINT_FUNC("Unpausing for resume\n"); + _pauseClientState = UNPAUSED; // Tell PM we're unpaused + } } - _pauseFlagOld = pause; } } /******************************************* * -* Function to be called by threads wanting to block on the PSP entering suspend -* Use this for small critical sections where you can easily restore the previous state. -* -********************************************/ -int PowerManager::blockOnSuspend() { - return beginCriticalSection(true); -} - -/******************************************* -* * Function to block on a suspend, then start a non-suspendable critical section * Use this for large or REALLY critical critical-sections. * Make sure to call endCriticalSection or the PSP won't suspend. +* returns true if blocked, false if not blocked ********************************************/ -int PowerManager::beginCriticalSection(bool justBlock) { +bool PowerManager::beginCriticalSection() { DEBUG_ENTER_FUNC(); - int ret = NotBlocked; - - if (SDL_mutexP(_flagMutex) != 0) { - PSP_ERROR("PowerManager::blockOnSuspend(): Couldn't lock flagMutex[%p]\n", _flagMutex); - ret = Error; - } + bool ret = false; + + _flagMutex.lock(); // Check the access flag - if (_suspendFlag == true) { - PSP_DEBUG_PRINT("We're being blocked!\n"); - debugPM(); - ret = Blocked; + if (_suspendFlag) { + ret = true; - // If it's true, we wait for a signal to continue - if (SDL_CondWait(_condSuspendable, _flagMutex) != 0) { - PSP_DEBUG_PRINT("PowerManager::blockOnSuspend(): Couldn't wait on cond[%p]\n", _condSuspendable); - } + PSP_DEBUG_PRINT("I got blocked. ThreadId[%x]\n", sceKernelGetThreadId()); + debugPM(); + + _threadSleep.wait(_flagMutex); - PSP_DEBUG_PRINT("We got blocked!!\n"); + PSP_DEBUG_PRINT_FUNC("I got released. ThreadId[%x]\n", sceKernelGetThreadId()); debugPM(); } // Now prevent the PM from suspending until we're done - if (justBlock == false) - _criticalCounter++; + _criticalCounter++; - if (SDL_mutexV(_flagMutex) != 0) { - PSP_ERROR("PowerManager::blockOnSuspend(): Couldn't unlock flagMutex[%p]\n", _flagMutex); - ret = Error; - } + _flagMutex.unlock(); return ret; } -int PowerManager::endCriticalSection() { +// returns success = true +void PowerManager::endCriticalSection() { DEBUG_ENTER_FUNC(); - int ret = 0; - if (SDL_mutexP(_flagMutex) != 0) { - PSP_ERROR("PowerManager::endCriticalSection(): Couldn't lock flagMutex[%p]\n", _flagMutex); - ret = Error; - } + _flagMutex.lock(); // We're done with our critical section _criticalCounter--; if (_criticalCounter <= 0) { - if (_suspendFlag == true) { // If the PM is sleeping, this flag must be set - PSP_DEBUG_PRINT("Unblocked thread waking up the PM.\n"); - debugPM(); - - SDL_CondBroadcast(_condPM); - - PSP_DEBUG_PRINT("Woke up the PM\n"); - debugPM(); + if (_suspendFlag) { // If the PM is sleeping, this flag must be set + PSP_DEBUG_PRINT_FUNC("PM is asleep. Waking it up.\n"); + debugPM(); + + _pmSleep.releaseAll(); + + PSP_DEBUG_PRINT_FUNC("Woke up the PM\n"); + + debugPM(); } if (_criticalCounter < 0) { // Check for bad usage of critical sections - PSP_ERROR("Critical counter[%d]\n", _criticalCounter); + PSP_ERROR("Critical counter[%d]!!!\n", _criticalCounter); debugPM(); } } - if (SDL_mutexV(_flagMutex) != 0) { - PSP_ERROR("Couldn't unlock flagMutex[%p]\n", _flagMutex); - ret = Error; - } - - return ret; + _flagMutex.unlock(); } /******************************************* @@ -286,90 +206,77 @@ int PowerManager::endCriticalSection() { * Callback function to be called to put every Suspendable to suspend * ********************************************/ -int PowerManager::suspend() { +void PowerManager::suspend() { DEBUG_ENTER_FUNC(); - int ret = 0; - if (_pauseFlag) return ret; // Very important - make sure we only suspend once + if (_pauseFlag) + return; // Very important - make sure we only suspend once - scePowerLock(0); // Critical to make sure PSP doesn't suspend before we're done + scePowerLock(0); // Also critical to make sure PSP doesn't suspend before we're done // The first stage of suspend is pausing the engine if possible. We don't want to cause files // to block, or we might not get the engine to pause. On the other hand, we might wait for polling // and it'll never happen. We also want to do this w/o mutexes (for speed) which is ok in this case. _pauseFlag = true; - PMStatusSet(kWaitForClientPause); + _PMStatus = kWaitForClientPause; // Now we wait, giving the engine thread some time to find our flag. - for (int i = 0; i < 10 && _pauseClientState == Unpaused; i++) - sceKernelDelayThread(50000); // We wait 50 msec x 10 times = 0.5 seconds + for (int i = 0; i < 10 && _pauseClientState == UNPAUSED; i++) + PspThread::delayMicros(50000); // We wait 50 msec x 10 times = 0.5 seconds - if (_pauseClientState == Pausing) { // Our event has been acknowledged. Let's wait until the client is done. - PMStatusSet(kWaitForClientToFinishPausing); + if (_pauseClientState == PAUSING) { // Our event has been acknowledged. Let's wait until the client is done. + _PMStatus = kWaitForClientToFinishPausing; - while (_pauseClientState != Paused) - sceKernelDelayThread(50000); // We wait 50 msec at a time + while (_pauseClientState != PAUSED) + PspThread::delayMicros(50000); // We wait 50 msec at a time } - // It's possible that the polling thread missed our pause event, but there's nothing we can do about that. - // We can't know if there's polling going on or not. It's usually not a critical thing anyway. + // It's possible that the polling thread missed our pause event, but there's + // nothing we can do about that. + // We can't know if there's polling going on or not. + // It's usually not a critical thing anyway. - PMStatusSet(kGettingFlagMutexSuspend); + _PMStatus = kGettingFlagMutexSuspend; // Now we set the suspend flag to true to cause reading threads to block + _flagMutex.lock(); - if (SDL_mutexP(_flagMutex) != 0) { - PSP_ERROR("Couldn't lock flagMutex[%p]\n", _flagMutex); - _error = Error; - ret = Error; - } - - PMStatusSet(kGotFlagMutexSuspend); + _PMStatus = kGotFlagMutexSuspend; _suspendFlag = true; // Check if anyone is in a critical section. If so, we'll wait for them if (_criticalCounter > 0) { - PMStatusSet(kWaitCritSectionSuspend); - SDL_CondWait(_condPM, _flagMutex); - PMStatusSet(kDoneWaitingCritSectionSuspend); - } + _PMStatus = kWaitCritSectionSuspend; + + _pmSleep.wait(_flagMutex); + + _PMStatus = kDoneWaitingCritSectionSuspend; + } + + _flagMutex.unlock(); - if (SDL_mutexV(_flagMutex) != 0) { - PSP_ERROR("Couldn't unlock flagMutex[%p]\n", _flagMutex); - _error = Error; - ret = Error; - } - - PMStatusSet(kGettingListMutexSuspend); + _PMStatus = kGettingListMutexSuspend; // Loop over list, calling suspend() - if (SDL_mutexP(_listMutex) != 0) { - PSP_ERROR("Couldn't lock listMutex[%p]\n", _listMutex); - _error = Error; - ret = Error; - } - PMStatusSet(kIteratingListSuspend); + _listMutex.lock(); + + _PMStatus = kIteratingListSuspend; // Iterate Common::List<Suspendable *>::iterator i; for (i = _suspendList.begin(); i != _suspendList.end(); ++i) { (*i)->suspend(); } + _PMStatus = kDoneIteratingListSuspend; - PMStatusSet(kDoneIteratingListSuspend); - - if (SDL_mutexV(_listMutex) != 0) { - PSP_ERROR("Couldn't unlock listMutex[%p]\n", _listMutex); - _error = Error; - ret = Error; - } - PMStatusSet(kDoneSuspend); + _listMutex.unlock(); + _PMStatus = kDoneSuspend; scePowerUnlock(0); // Allow the PSP to go to sleep now - - return ret; + + _PMStatus = kDonePowerUnlock; } /******************************************* @@ -377,24 +284,26 @@ int PowerManager::suspend() { * Callback function to resume every Suspendable * ********************************************/ -int PowerManager::resume() { +void PowerManager::resume() { DEBUG_ENTER_FUNC(); - int ret = 0; + + _PMStatus = kBeginResume; // Make sure we can't get another suspend scePowerLock(0); - if (!_pauseFlag) return ret; // Make sure we can only resume once + _PMStatus = kCheckingPauseFlag; + + if (!_pauseFlag) + return; // Make sure we can only resume once - PMStatusSet(kGettingListMutexResume); + _PMStatus = kGettingListMutexResume; // First we notify our Suspendables. Loop over list, calling resume() - if (SDL_mutexP(_listMutex) != 0) { - PSP_ERROR("Couldn't lock listMutex[%p]\n", _listMutex); - _error = Error; - ret = Error; - } - PMStatusSet(kIteratingListResume); + _listMutex.lock(); + + _PMStatus = kIteratingListResume; + // Iterate Common::List<Suspendable *>::iterator i = _suspendList.begin(); @@ -402,46 +311,31 @@ int PowerManager::resume() { (*i)->resume(); } - PMStatusSet(kDoneIteratingListResume); + _PMStatus = kDoneIteratingListResume; - if (SDL_mutexV(_listMutex) != 0) { - PSP_ERROR("Couldn't unlock listMutex[%p]\n", _listMutex); - _error = Error; - ret = Error; - } - - PMStatusSet(kGettingFlagMutexResume); + _listMutex.unlock(); + + _PMStatus = kGettingFlagMutexResume; // Now we set the suspend flag to false - if (SDL_mutexP(_flagMutex) != 0) { - PSP_ERROR("Couldn't lock flagMutex %p\n", _flagMutex); - _error = Error; - ret = Error; - } - PMStatusSet(kGotFlagMutexResume); + _flagMutex.lock(); + + _PMStatus = kGotFlagMutexResume; _suspendFlag = false; - PMStatusSet(kSignalSuspendedThreadsResume); + _PMStatus = kSignalSuspendedThreadsResume; - // Signal the other threads to wake up - if (SDL_CondBroadcast(_condSuspendable) != 0) { - PSP_ERROR("Couldn't broadcast condition[%p]\n", _condSuspendable); - _error = Error; - ret = Error; - } - PMStatusSet(kDoneSignallingSuspendedThreadsResume); + // Signal the threads to wake up + _threadSleep.releaseAll(); + + _PMStatus = kDoneSignallingSuspendedThreadsResume; - if (SDL_mutexV(_flagMutex) != 0) { - PSP_ERROR("Couldn't unlock flagMutex[%p]\n", _flagMutex); - _error = Error; - ret = Error; - } - PMStatusSet(kDoneResume); + _flagMutex.unlock(); + + _PMStatus = kDoneResume; - _pauseFlag = false; // Signal engine to unpause + _pauseFlag = false; // Signal engine to unpause -- no mutex needed scePowerUnlock(0); // Allow new suspends - - return ret; } diff --git a/backends/platform/psp/powerman.h b/backends/platform/psp/powerman.h index af3134adee..5f09bc7794 100644 --- a/backends/platform/psp/powerman.h +++ b/backends/platform/psp/powerman.h @@ -26,8 +26,7 @@ #ifndef POWERMAN_H #define POWERMAN_H -#include <SDL/SDL_thread.h> -#include <SDL/SDL_mutex.h> +#include "backends/platform/psp/thread.h" #include "common/singleton.h" #include "common/list.h" @@ -53,12 +52,12 @@ class PowerManager: public Common::Singleton<PowerManager> { public: int blockOnSuspend(); /* block if suspending */ - int beginCriticalSection(bool justBlock = false); /* Use a critical section to block (if suspend was already pressed) */ - int endCriticalSection(); /* and to prevent the PSP from suspending in a particular section */ - int registerSuspend(Suspendable *item); /* register to be called to suspend/resume */ - int unregisterSuspend(Suspendable *item); /* remove from suspend/resume list */ - int suspend(); /* callback to have all items in list suspend */ - int resume(); /* callback to have all items in list resume */ + bool beginCriticalSection(); /* Use a critical section to block (if suspend was already pressed) */ + void endCriticalSection(); /* and to prevent the PSP from suspending in a particular section */ + bool registerForSuspend(Suspendable *item); /* register to be called to suspend/resume */ + bool unregisterForSuspend(Suspendable *item); /* remove from suspend/resume list */ + void suspend(); /* callback to have all items in list suspend */ + void resume(); /* callback to have all items in list resume */ // Functions for pausing the engine void pollPauseEngine(); /* Poll whether the engine should be paused */ @@ -69,11 +68,9 @@ public: }; enum PauseState { - Unpaused = 0, - PauseEvent, - UnpauseEvent, - Pausing, - Paused + UNPAUSED = 0, + PAUSING, + PAUSED }; private: @@ -81,34 +78,38 @@ private: PowerManager(); ~PowerManager(); - Common::List<Suspendable *> _suspendList; /* list to register in */ + Common::List<Suspendable *> _suspendList; // list to register in - volatile bool _pauseFlag; /* For pausing, which is before suspending */ - volatile bool _pauseFlagOld; /* Save the last state of the flag while polling */ - volatile int _pauseClientState; /* Pause state of the target */ + volatile bool _pauseFlag; // For pausing, which is before suspending + volatile bool _pauseFlagOld; // Save the last state of the flag while polling + volatile PauseState _pauseClientState; // Pause state of the target - volatile bool _suspendFlag; /* protected variable */ - SDL_mutex *_flagMutex; /* mutex to access access flag */ - SDL_mutex *_listMutex; /* mutex to access Suspendable list */ - SDL_cond *_condSuspendable; /* signal to synchronize accessing threads */ - SDL_cond *_condPM; /* signal to wake up the PM from a critical section */ - volatile int _criticalCounter; /* Counter of how many threads are in a critical section */ - int _error; /* error code - PM can't talk to us. For debugging */ + volatile bool _suspendFlag; // protected variable + PspMutex _flagMutex; // mutex to access access flag + PspMutex _listMutex; // mutex to access Suspendable list + PspCondition _threadSleep; // signal to synchronize accessing threads + PspCondition _pmSleep; // signal to wake up the PM from a critical section + volatile int _criticalCounter; // Counter of how many threads are in a critical section + int _error; // error code - PM can't talk to us. For debugging + volatile int _PMStatus; // What the PM is doing. for debugging // States for PM to be in (used for debugging) enum PMState { - kInitDone = 1 , - kDestroyPM, - kWaitForClientPause, - kWaitForClientToFinishPausing, - kGettingFlagMutexSuspend, - kGotFlagMutexSuspend, - kWaitCritSectionSuspend, - kDoneWaitingCritSectionSuspend, - kGettingListMutexSuspend, - kIteratingListSuspend, - kDoneIteratingListSuspend, - kDoneSuspend, + kInitDone = 1, + kDestroyPM = 2, + kWaitForClientPause = 3, + kWaitForClientToFinishPausing = 4, + kGettingFlagMutexSuspend = 5, + kGotFlagMutexSuspend = 6, + kWaitCritSectionSuspend = 7, + kDoneWaitingCritSectionSuspend = 8, + kGettingListMutexSuspend = 9, + kIteratingListSuspend = 10, + kDoneIteratingListSuspend = 11, + kDoneSuspend = 12, + kDonePowerUnlock, + kBeginResume, + kCheckingPauseFlag, kGettingListMutexResume, kIteratingListResume, kDoneIteratingListResume, @@ -122,8 +123,6 @@ private: volatile int _listCounter; /* How many people are in the list - just for debugging */ void debugPM(); /* print info about the PM */ - void PMStatusSet(PMState s) { _PMStatus = s; } - volatile int _PMStatus; /* What the PM is doing */ public: int getPMStatus() const { return _PMStatus; } diff --git a/backends/platform/psp/psp_main.cpp b/backends/platform/psp/psp_main.cpp index e6940eba13..c26aed539e 100644 --- a/backends/platform/psp/psp_main.cpp +++ b/backends/platform/psp/psp_main.cpp @@ -110,12 +110,13 @@ int exit_callback(void) { } /* Function for handling suspend/resume */ -void power_callback(int , int powerinfo) { +int power_callback(int , int powerinfo, void *) { if (powerinfo & PSP_POWER_CB_POWER_SWITCH || powerinfo & PSP_POWER_CB_SUSPENDING) { PowerMan.suspend(); } else if (powerinfo & PSP_POWER_CB_RESUME_COMPLETE) { PowerMan.resume(); } + return 0; } /* Callback thread */ diff --git a/backends/platform/psp/psploader.cpp b/backends/platform/psp/psploader.cpp index 68e51c1a50..464e20770c 100644 --- a/backends/platform/psp/psploader.cpp +++ b/backends/platform/psp/psploader.cpp @@ -37,24 +37,20 @@ #include "backends/platform/psp/psploader.h" #include "backends/platform/psp/powerman.h" -//#define __PSP_DEBUG_PLUGINS__ +//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */ +//#define __PSP_DEBUG_PRINT__ -#ifdef __PSP_DEBUG_PLUGINS__ -#define DBG(x,...) fprintf(stderr,x, ## __VA_ARGS__) -#else -#define DBG(x,...) -#endif - -#define seterror(x,...) fprintf(stderr,x, ## __VA_ARGS__) +#include "backends/platform/psp/trace.h" extern char __plugin_hole_start; // Indicates start of hole in program file for shorts extern char __plugin_hole_end; // Indicates end of hole in program file -extern char _gp[]; // Value of gp register +extern char _gp[]; // Value of gp register DECLARE_SINGLETON(ShortSegmentManager) // For singleton // Get rid of symbol table in memory void DLObject::discard_symtab() { + DEBUG_ENTER_FUNC(); free(_symtab); free(_strtab); _symtab = NULL; @@ -64,6 +60,7 @@ void DLObject::discard_symtab() { // Unload all objects from memory void DLObject::unload() { + DEBUG_ENTER_FUNC(); discard_symtab(); free(_segment); _segment = NULL; @@ -84,18 +81,19 @@ void DLObject::unload() { * */ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void *relSegment) { + DEBUG_ENTER_FUNC(); Elf32_Rel *rel = NULL; // relocation entry // Allocate memory for relocation table if (!(rel = (Elf32_Rel *)malloc(size))) { - seterror("Out of memory."); + PSP_ERROR("Out of memory."); return false; } // Read in our relocation table if (lseek(fd, offset, SEEK_SET) < 0 || read(fd, rel, size) != (ssize_t)size) { - seterror("Relocation table load failed."); + PSP_ERROR("Relocation table load failed."); free(rel); return false; } @@ -103,7 +101,7 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void * // Treat each relocation entry. Loop over all of them int cnt = size / sizeof(*rel); - DBG("Loaded relocation table. %d entries. base address=%p\n", cnt, relSegment); + PSP_DEBUG_PRINT("Loaded relocation table. %d entries. base address=%p\n", cnt, relSegment); bool seenHi16 = false; // For treating HI/LO16 commands int firstHi16 = -1; // Mark the point of the first hi16 seen @@ -127,7 +125,7 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void * // Get the target instruction in the code unsigned int *target = (unsigned int *)((char *)relSegment + rel[i].r_offset); - unsigned int origTarget = *target; // Save for debugging + PSP_DEBUG_DO(unsigned int origTarget = *target); // Save for debugging // Act differently based on the type of relocation switch (REL_TYPE(rel[i].r_info)) { @@ -142,7 +140,7 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void * lastHiSymVal = sym->st_value; hi16InShorts = (ShortsMan.inGeneralSegment((char *)sym->st_value)); // Fix for problem with switching btw segments if (debugRelocs[0]++ < DEBUG_NUM) // Print only a set number - DBG("R_MIPS_HI16: i=%d, offset=%x, ahl = %x, target = %x\n", + PSP_DEBUG_PRINT("R_MIPS_HI16: i=%d, offset=%x, ahl = %x, target = %x\n", i, rel[i].r_offset, ahl, *target); } break; @@ -150,7 +148,7 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void * case R_MIPS_LO16: // Absolute addressing. Needs a HI16 to come before it if (sym->st_shndx < SHN_LOPROC) { // Only shift for plugin section. (ie. has a real section index) if (!seenHi16) { // We MUST have seen HI16 first - seterror("R_MIPS_LO16 w/o preceding R_MIPS_HI16 at relocation %d!\n", i); + PSP_ERROR("R_MIPS_LO16 w/o preceding R_MIPS_HI16 at relocation %d!\n", i); free(rel); return false; } @@ -195,10 +193,10 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void * *target |= relocation & 0xffff; // Take the lower 16 bits of the relocation if (debugRelocs[1]++ < DEBUG_NUM) - DBG("R_MIPS_LO16: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n", + PSP_DEBUG_PRINT("R_MIPS_LO16: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n", i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target); if (lo16InShorts && debugRelocs[2]++ < DEBUG_NUM) - DBG("R_MIPS_LO16s: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n", + PSP_DEBUG_PRINT("R_MIPS_LO16s: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n", i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target); } break; @@ -212,11 +210,11 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void * *target |= (relocation & 0x03ffffff); if (debugRelocs[3]++ < DEBUG_NUM) - DBG("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n", + PSP_DEBUG_PRINT("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n", i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target); } else { if (debugRelocs[4]++ < DEBUG_NUM) - DBG("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n", + PSP_DEBUG_PRINT("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n", i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target); } break; @@ -233,7 +231,7 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void * *target |= relocation & 0xffff; if (debugRelocs[5]++ < DEBUG_NUM) - DBG("R_MIPS_GPREL16: i=%d, a=%x, gpVal=%x, origTarget=%x, target=%x, offset=%x\n", + PSP_DEBUG_PRINT("R_MIPS_GPREL16: i=%d, a=%x, gpVal=%x, origTarget=%x, target=%x, offset=%x\n", i, a, _gpVal, origTarget, *target, _shortsSegment->getOffset()); } @@ -250,24 +248,25 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void * *target = relocation; if (debugRelocs[6]++ < DEBUG_NUM) - DBG("R_MIPS_32: i=%d, a=%x, origTarget=%x, target=%x\n", i, a, origTarget, *target); + PSP_DEBUG_PRINT("R_MIPS_32: i=%d, a=%x, origTarget=%x, target=%x\n", i, a, origTarget, *target); } break; default: - seterror("Unknown relocation type %x at relocation %d.\n", REL_TYPE(rel[i].r_info), i); + PSP_ERROR("Unknown relocation type %x at relocation %d.\n", REL_TYPE(rel[i].r_info), i); free(rel); return false; } } - DBG("Done with relocation. extendedHi16=%d\n\n", extendedHi16); + PSP_DEBUG_PRINT("Done with relocation. extendedHi16=%d\n\n", extendedHi16); free(rel); return true; } bool DLObject::readElfHeader(int fd, Elf32_Ehdr *ehdr) { + DEBUG_ENTER_FUNC(); // Start reading the elf header. Check for errors if (read(fd, ehdr, sizeof(*ehdr)) != sizeof(*ehdr) || memcmp(ehdr->e_ident, ELFMAG, SELFMAG) || // Check MAGIC @@ -275,31 +274,32 @@ bool DLObject::readElfHeader(int fd, Elf32_Ehdr *ehdr) { ehdr->e_machine != EM_MIPS || // Check for MIPS machine type ehdr->e_phentsize < sizeof(Elf32_Phdr) || // Check for size of program header ehdr->e_shentsize != sizeof(Elf32_Shdr)) { // Check for size of section header - seterror("Invalid file type."); + PSP_ERROR("Invalid file type."); return false; } - DBG("phoff = %d, phentsz = %d, phnum = %d\n", + PSP_DEBUG_PRINT("phoff = %d, phentsz = %d, phnum = %d\n", ehdr->e_phoff, ehdr->e_phentsize, ehdr->e_phnum); return true; } bool DLObject::readProgramHeaders(int fd, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, int num) { + DEBUG_ENTER_FUNC(); // Read program header if (lseek(fd, ehdr->e_phoff + sizeof(*phdr)*num, SEEK_SET) < 0 || read(fd, phdr, sizeof(*phdr)) != sizeof(*phdr)) { - seterror("Program header load failed."); + PSP_ERROR("Program header load failed."); return false; } // Check program header values if (phdr->p_type != PT_LOAD || phdr->p_filesz > phdr->p_memsz) { - seterror("Invalid program header."); + PSP_ERROR("Invalid program header."); return false; } - DBG("offs = %x, filesz = %x, memsz = %x, align = %x\n", + PSP_DEBUG_PRINT("offs = %x, filesz = %x, memsz = %x, align = %x\n", phdr->p_offset, phdr->p_filesz, phdr->p_memsz, phdr->p_align); return true; @@ -307,6 +307,7 @@ bool DLObject::readProgramHeaders(int fd, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, in } bool DLObject::loadSegment(int fd, Elf32_Phdr *phdr) { + DEBUG_ENTER_FUNC(); char *baseAddress = 0; @@ -315,15 +316,15 @@ bool DLObject::loadSegment(int fd, Elf32_Phdr *phdr) { // Attempt to allocate memory for segment int extra = phdr->p_vaddr % phdr->p_align; // Get extra length TODO: check logic here - DBG("extra mem is %x\n", extra); + PSP_DEBUG_PRINT("extra mem is %x\n", extra); if (phdr->p_align < 0x10000) phdr->p_align = 0x10000; // Fix for wrong alignment on e.g. AGI if (!(_segment = (char *)memalign(phdr->p_align, phdr->p_memsz + extra))) { - seterror("Out of memory.\n"); + PSP_ERROR("Out of memory.\n"); return false; } - DBG("allocated segment @ %p\n", _segment); + PSP_DEBUG_PRINT("allocated segment @ %p\n", _segment); // Get offset to load segment into baseAddress = (char *)_segment + phdr->p_vaddr; @@ -332,20 +333,20 @@ bool DLObject::loadSegment(int fd, Elf32_Phdr *phdr) { _shortsSegment = ShortsMan.newSegment(phdr->p_memsz, (char *)phdr->p_vaddr); baseAddress = _shortsSegment->getStart(); - DBG("shorts segment @ %p to %p. Segment wants to be at %x. Offset=%x\n", + PSP_DEBUG_PRINT("shorts segment @ %p to %p. Segment wants to be at %x. Offset=%x\n", _shortsSegment->getStart(), _shortsSegment->getEnd(), phdr->p_vaddr, _shortsSegment->getOffset()); } // Set bss segment to 0 if necessary (assumes bss is at the end) if (phdr->p_memsz > phdr->p_filesz) { - DBG("Setting %p to %p to 0 for bss\n", baseAddress + phdr->p_filesz, baseAddress + phdr->p_memsz); + PSP_DEBUG_PRINT("Setting %p to %p to 0 for bss\n", baseAddress + phdr->p_filesz, baseAddress + phdr->p_memsz); memset(baseAddress + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz); } // Read the segment into memory if (lseek(fd, phdr->p_offset, SEEK_SET) < 0 || read(fd, baseAddress, phdr->p_filesz) != (ssize_t)phdr->p_filesz) { - seterror("Segment load failed."); + PSP_ERROR("Segment load failed."); return false; } @@ -354,12 +355,13 @@ bool DLObject::loadSegment(int fd, Elf32_Phdr *phdr) { Elf32_Shdr * DLObject::loadSectionHeaders(int fd, Elf32_Ehdr *ehdr) { + DEBUG_ENTER_FUNC(); Elf32_Shdr *shdr = NULL; // Allocate memory for section headers if (!(shdr = (Elf32_Shdr *)malloc(ehdr->e_shnum * sizeof(*shdr)))) { - seterror("Out of memory."); + PSP_ERROR("Out of memory."); return NULL; } @@ -367,7 +369,7 @@ Elf32_Shdr * DLObject::loadSectionHeaders(int fd, Elf32_Ehdr *ehdr) { if (lseek(fd, ehdr->e_shoff, SEEK_SET) < 0 || read(fd, shdr, ehdr->e_shnum * sizeof(*shdr)) != (ssize_t)(ehdr->e_shnum * sizeof(*shdr))) { - seterror("Section headers load failed."); + PSP_ERROR("Section headers load failed."); return NULL; } @@ -375,11 +377,12 @@ Elf32_Shdr * DLObject::loadSectionHeaders(int fd, Elf32_Ehdr *ehdr) { } int DLObject::loadSymbolTable(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { + DEBUG_ENTER_FUNC(); // Loop over sections, looking for symbol table linked to a string table for (int i = 0; i < ehdr->e_shnum; i++) { - //DBG("Section %d: type = %x, size = %x, entsize = %x, link = %x\n", - // i, shdr[i].sh_type, shdr[i].sh_size, shdr[i].sh_entsize, shdr[i].sh_link); + PSP_DEBUG_PRINT("Section %d: type = %x, size = %x, entsize = %x, link = %x\n", + i, shdr[i].sh_type, shdr[i].sh_size, shdr[i].sh_entsize, shdr[i].sh_link); if (shdr[i].sh_type == SHT_SYMTAB && shdr[i].sh_entsize == sizeof(Elf32_Sym) && @@ -392,15 +395,15 @@ int DLObject::loadSymbolTable(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { // Check for no symbol table if (_symtab_sect < 0) { - seterror("No symbol table."); + PSP_ERROR("No symbol table."); return -1; } - DBG("Symbol section at section %d, size %x\n", _symtab_sect, shdr[_symtab_sect].sh_size); + PSP_DEBUG_PRINT("Symbol section at section %d, size %x\n", _symtab_sect, shdr[_symtab_sect].sh_size); // Allocate memory for symbol table if (!(_symtab = malloc(shdr[_symtab_sect].sh_size))) { - seterror("Out of memory."); + PSP_ERROR("Out of memory."); return -1; } @@ -408,25 +411,26 @@ int DLObject::loadSymbolTable(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { if (lseek(fd, shdr[_symtab_sect].sh_offset, SEEK_SET) < 0 || read(fd, _symtab, shdr[_symtab_sect].sh_size) != (ssize_t)shdr[_symtab_sect].sh_size) { - seterror("Symbol table load failed."); + PSP_ERROR("Symbol table load failed."); return -1; } // Set number of symbols _symbol_cnt = shdr[_symtab_sect].sh_size / sizeof(Elf32_Sym); - DBG("Loaded %d symbols.\n", _symbol_cnt); + PSP_DEBUG_PRINT("Loaded %d symbols.\n", _symbol_cnt); return _symtab_sect; } bool DLObject::loadStringTable(int fd, Elf32_Shdr *shdr) { + DEBUG_ENTER_FUNC(); int string_sect = shdr[_symtab_sect].sh_link; // Allocate memory for string table if (!(_strtab = (char *)malloc(shdr[string_sect].sh_size))) { - seterror("Out of memory."); + PSP_ERROR("Out of memory."); return false; } @@ -434,16 +438,17 @@ bool DLObject::loadStringTable(int fd, Elf32_Shdr *shdr) { if (lseek(fd, shdr[string_sect].sh_offset, SEEK_SET) < 0 || read(fd, _strtab, shdr[string_sect].sh_size) != (ssize_t)shdr[string_sect].sh_size) { - seterror("Symbol table strings load failed."); + PSP_ERROR("Symbol table strings load failed."); return false; } return true; } void DLObject::relocateSymbols(Elf32_Addr offset, Elf32_Addr shortsOffset) { + DEBUG_ENTER_FUNC(); int shortsCount = 0, othersCount = 0; - DBG("Relocating symbols by %x. Shorts offset=%x\n", offset, shortsOffset); + PSP_DEBUG_PRINT("Relocating symbols by %x. Shorts offset=%x\n", offset, shortsOffset); // Loop over symbols, add relocation offset Elf32_Sym *s = (Elf32_Sym *)_symtab; @@ -454,22 +459,23 @@ void DLObject::relocateSymbols(Elf32_Addr offset, Elf32_Addr shortsOffset) { othersCount++; s->st_value += offset; if (s->st_value < (Elf32_Addr)_segment || s->st_value > (Elf32_Addr)_segment + _segmentSize) - seterror("Symbol out of bounds! st_value = %x\n", s->st_value); + PSP_ERROR("Symbol out of bounds! st_value = %x\n", s->st_value); } else { // shorts section shortsCount++; s->st_value += shortsOffset; if (!_shortsSegment->inSegment((char *)s->st_value)) - seterror("Symbol out of bounds! st_value = %x\n", s->st_value); + PSP_ERROR("Symbol out of bounds! st_value = %x\n", s->st_value); } } } - DBG("Relocated %d short symbols, %d others.\n", shortsCount, othersCount); + PSP_DEBUG_PRINT("Relocated %d short symbols, %d others.\n", shortsCount, othersCount); } bool DLObject::relocateRels(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { + DEBUG_ENTER_FUNC(); // Loop over sections, finding relocation sections for (int i = 0; i < ehdr->e_shnum; i++) { @@ -500,7 +506,7 @@ bool DLObject::relocateRels(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) { bool DLObject::load(int fd) { - fprintf(stderr, "In DLObject::load\n"); + DEBUG_ENTER_FUNC(); Elf32_Ehdr ehdr; // ELF header Elf32_Phdr phdr; // Program header @@ -512,8 +518,7 @@ bool DLObject::load(int fd) { } for (int i = 0; i < ehdr.e_phnum; i++) { // Load our 2 segments - - fprintf(stderr, "Loading segment %d\n", i); + PSP_DEBUG_PRINT("Loading segment %d\n", i); if (readProgramHeaders(fd, &ehdr, &phdr, i) == false) return false; @@ -543,19 +548,20 @@ bool DLObject::load(int fd) { } bool DLObject::open(const char *path) { + DEBUG_ENTER_FUNC(); int fd; void *ctors_start, *ctors_end; - DBG("open(\"%s\")\n", path); + PSP_DEBUG_PRINT("open(\"%s\")\n", path); // Get the address of the global pointer _gpVal = (unsigned int) & _gp; - DBG("_gpVal is %x\n", _gpVal); + PSP_DEBUG_PRINT("_gpVal is %x\n", _gpVal); PowerMan.beginCriticalSection(); if ((fd = ::open(path, O_RDONLY)) < 0) { - seterror("%s not found.", path); + PSP_ERROR("%s not found.", path); return false; } @@ -581,21 +587,22 @@ bool DLObject::open(const char *path) { if (ctors_start == NULL || ctors_end == NULL || _dtors_start == NULL || _dtors_end == NULL) { - seterror("Missing ctors/dtors."); + PSP_ERROR("Missing ctors/dtors."); _dtors_start = _dtors_end = NULL; unload(); return false; } - DBG("Calling constructors.\n"); + PSP_DEBUG_PRINT("Calling constructors.\n"); for (void (**f)(void) = (void (**)(void))ctors_start; f != ctors_end; f++) (**f)(); - DBG("%s opened ok.\n", path); + PSP_DEBUG_PRINT("%s opened ok.\n", path); return true; } bool DLObject::close() { + DEBUG_ENTER_FUNC(); if (_dtors_start != NULL && _dtors_end != NULL) for (void (**f)(void) = (void (**)(void))_dtors_start; f != _dtors_end; f++) (**f)(); @@ -605,10 +612,11 @@ bool DLObject::close() { } void *DLObject::symbol(const char *name) { - DBG("symbol(\"%s\")\n", name); + DEBUG_ENTER_FUNC(); + PSP_DEBUG_PRINT("symbol(\"%s\")\n", name); if (_symtab == NULL || _strtab == NULL || _symbol_cnt < 1) { - seterror("No symbol table loaded."); + PSP_ERROR("No symbol table loaded."); return NULL; } @@ -621,23 +629,25 @@ void *DLObject::symbol(const char *name) { !strcmp(name, _strtab + s->st_name)) { // We found the symbol - DBG("=> %p\n", (void*)s->st_value); + PSP_DEBUG_PRINT("=> %p\n", (void*)s->st_value); return (void*)s->st_value; } } - seterror("Symbol \"%s\" not found.", name); + PSP_ERROR("Symbol \"%s\" not found.", name); return NULL; } ShortSegmentManager::ShortSegmentManager() { + DEBUG_ENTER_FUNC(); _shortsStart = &__plugin_hole_start ; _shortsEnd = &__plugin_hole_end; } ShortSegmentManager::Segment *ShortSegmentManager::newSegment(int size, char *origAddr) { + DEBUG_ENTER_FUNC(); char *lastAddress = origAddr; Common::List<Segment *>::iterator i; @@ -654,7 +664,7 @@ ShortSegmentManager::Segment *ShortSegmentManager::newSegment(int size, char *or lastAddress += 4 - ((Elf32_Addr)lastAddress & 3); // Round up to multiple of 4 if (lastAddress + size > _shortsEnd) { - seterror("Error. No space in shorts segment for %x bytes. Last address is %p, max address is %p.\n", + PSP_ERROR("No space in shorts segment for %x bytes. Last address is %p, max address is %p.\n", size, lastAddress, _shortsEnd); return NULL; } @@ -665,14 +675,15 @@ ShortSegmentManager::Segment *ShortSegmentManager::newSegment(int size, char *or _list.insert(i, seg); - DBG("Shorts segment size %x allocated. End = %p. Remaining space = %x. Highest so far is %p.\n", + PSP_DEBUG_PRINT("Shorts segment size %x allocated. End = %p. Remaining space = %x. Highest so far is %p.\n", size, lastAddress + size, _shortsEnd - _list.back()->getEnd(), _highestAddress); return seg; } void ShortSegmentManager::deleteSegment(ShortSegmentManager::Segment *seg) { - DBG("Deleting shorts segment from %p to %p.\n\n", seg->getStart(), seg->getEnd()); + DEBUG_ENTER_FUNC(); + PSP_DEBUG_PRINT("Deleting shorts segment from %p to %p.\n\n", seg->getStart(), seg->getEnd()); _list.remove(seg); delete seg; } diff --git a/backends/platform/psp/rtc.cpp b/backends/platform/psp/rtc.cpp new file mode 100644 index 0000000000..57edea7e49 --- /dev/null +++ b/backends/platform/psp/rtc.cpp @@ -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.cpp $ + * $Id: osys_psp.cpp 49903 2010-06-16 09:04:27Z Bluddy $ + * + */ + +#include <time.h> +#include <psptypes.h> +#include <psprtc.h> + +#include "common/scummsys.h" +#include "backends/platform/psp/rtc.h" + +//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */ +//#define __PSP_DEBUG_PRINT__ /* For debug printouts */ + +#include "backends/platform/psp/trace.h" + + +// Class PspRtc --------------------------------------------------------------- +DECLARE_SINGLETON(PspRtc) + +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]; +} + diff --git a/backends/platform/psp/rtc.h b/backends/platform/psp/rtc.h new file mode 100644 index 0000000000..7c1a28474d --- /dev/null +++ b/backends/platform/psp/rtc.h @@ -0,0 +1,50 @@ +/* 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 49903 2010-06-16 09:04:27Z Bluddy $ + * + */ + +#ifndef _PSP_RTC_H_ +#define _PSP_RTC_H_ + +#include "common/singleton.h" + +class PspRtc : public Common::Singleton<PspRtc> { +private: + uint32 _startMillis; + uint32 _startMicros; + uint32 _lastMillis; + uint32 _milliOffset; // to prevent looping around of millis + bool _looped; // make sure we only loop once - for threading +public: + PspRtc() + : _startMillis(0), _startMicros(0), + _lastMillis(0), _milliOffset(0), + _looped(false) { + init(); + } + void init(); + uint32 getMillis(); + uint32 getMicros(); +}; + +#endif
\ No newline at end of file diff --git a/backends/platform/psp/thread.cpp b/backends/platform/psp/thread.cpp index 4e7d5eada9..c19ff5f9e3 100644 --- a/backends/platform/psp/thread.cpp +++ b/backends/platform/psp/thread.cpp @@ -23,14 +23,13 @@ * */ -#include <time.h> -#include <psptypes.h> -#include <psprtc.h> #include <pspthreadman.h> #include "backends/platform/psp/thread.h" #include "backends/platform/psp/trace.h" +// Class PspThread -------------------------------------------------- + void PspThread::delayMillis(uint32 ms) { sceKernelDelayThread(ms * 1000); } @@ -39,49 +38,154 @@ void PspThread::delayMicros(uint32 us) { sceKernelDelayThread(us); } -void PspRtc::init() { // init our starting ticks - uint32 ticks[2]; - sceRtcGetCurrentTick((u64 *)ticks); +// Class PspSemaphore ------------------------------------------------ +//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */ +//#define __PSP_DEBUG_PRINT__ /* For debug printouts */ + +#include "backends/platform/psp/trace.h" - _startMillis = ticks[0]/1000; - _startMicros = ticks[0]; - //_lastMillis = ticks[0]/1000; //debug - only when we don't subtract startMillis +PspSemaphore::PspSemaphore(int initialValue, int maxValue/*=255*/) { + DEBUG_ENTER_FUNC(); + _handle = 0; + _handle = (uint32)sceKernelCreateSema("ScummVM Sema", 0 /* attr */, + initialValue, maxValue, + 0 /*option*/); + if (!_handle) + PSP_ERROR("failed to create semaphore.\n"); } -#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 */ +PspSemaphore::~PspSemaphore() { + DEBUG_ENTER_FUNC(); + if (_handle) + if (sceKernelDeleteSema((SceUID)_handle) < 0) + PSP_ERROR("failed to delete semaphore.\n"); +} -// 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]; +int PspSemaphore::numOfWaitingThreads() { + DEBUG_ENTER_FUNC(); + SceKernelSemaInfo info; + info.numWaitThreads = 0; - sceRtcGetCurrentTick((u64 *)ticks); // can introduce weird thread delays + if (sceKernelReferSemaStatus((SceUID)_handle, &info) < 0) + PSP_ERROR("failed to retrieve semaphore info for handle %d\n", _handle); + + return info.numWaitThreads; +} + +int PspSemaphore::getValue() { + DEBUG_ENTER_FUNC(); + SceKernelSemaInfo info; + info.currentCount = 0; - 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; - } + if (sceKernelReferSemaStatus((SceUID)_handle, &info) < 0) + PSP_ERROR("failed to retrieve semaphore info for handle %d\n", _handle); + + return info.currentCount; +} + +bool PspSemaphore::pollForValue(int value) { + DEBUG_ENTER_FUNC(); + if (sceKernelPollSema((SceUID)_handle, value) < 0) + return false; + + return true; +} + +// false: timeout or error +bool PspSemaphore::takeWithTimeOut(uint32 timeOut) { + DEBUG_ENTER_FUNC(); - _lastMillis = millis; + uint32 *pTimeOut = 0; + if (timeOut) + pTimeOut = &timeOut; - return millis + _milliOffset; + if (sceKernelWaitSema(_handle, 1, pTimeOut) < 0) // we always wait for 1 + return false; + return true; } -uint32 PspRtc::getMicros() { - uint32 ticks[2]; +bool PspSemaphore::give(int num /*=1*/) { + DEBUG_ENTER_FUNC(); - sceRtcGetCurrentTick((u64 *)ticks); - ticks[0] -= _startMicros; + if (sceKernelSignalSema((SceUID)_handle, num) < 0) + return false; + return true; +} + +// Class PspMutex ------------------------------------------------------------ + +bool PspMutex::lock() { + DEBUG_ENTER_FUNC(); + int threadId = sceKernelGetThreadId(); + bool ret = true; - return ticks[0]; + if (_ownerId == threadId) { + _recursiveCount++; + } else { + ret = _semaphore.take(); + _ownerId = threadId; + _recursiveCount = 0; + } + return ret; +} + +bool PspMutex::unlock() { + DEBUG_ENTER_FUNC(); + int threadId = sceKernelGetThreadId(); + bool ret = true; + + if (_ownerId != threadId) { + PSP_ERROR("attempt to unlock mutex by thread[%x] as opposed to owner[%x]\n", + threadId, _ownerId); + return false; + } + + if (_recursiveCount) { + _recursiveCount--; + } else { + _ownerId = 0; + ret = _semaphore.give(1); + } + return ret; +} + +// Class PspCondition ------------------------------------------------- + +// Release all threads waiting on the condition +void PspCondition::releaseAll() { + _mutex.lock(); + if (_waitingThreads > _signaledThreads) { // we have signals to issue + int numWaiting = _waitingThreads - _signaledThreads; // threads we haven't signaled + _signaledThreads = _waitingThreads; + + _waitSem.give(numWaiting); + _mutex.unlock(); + for (int i=0; i<numWaiting; i++) // wait for threads to tell us they're awake + _doneSem.take(); + } else { + _mutex.unlock(); + } +} + +// Mutex must be taken before entering wait +void PspCondition::wait(PspMutex &externalMutex) { + _mutex.lock(); + _waitingThreads++; + _mutex.unlock(); + + externalMutex.unlock(); // must unlock external mutex + + _waitSem.take(); // sleep on the wait semaphore + + // let the signaling thread know we're done + _mutex.lock(); + if (_signaledThreads > 0 ) { + _doneSem.give(); // let the thread know + _signaledThreads--; + } + _waitingThreads--; + _mutex.unlock(); + + externalMutex.lock(); // must lock external mutex here for continuation } diff --git a/backends/platform/psp/thread.h b/backends/platform/psp/thread.h index 380159fa2d..27d53903d6 100644 --- a/backends/platform/psp/thread.h +++ b/backends/platform/psp/thread.h @@ -34,18 +34,46 @@ public: static void delayMicros(uint32 us); }; -class PspRtc { +class PspSemaphore { private: - uint32 _startMillis; - uint32 _startMicros; - uint32 _lastMillis; - uint32 _milliOffset; // to prevent looping around of millis - bool _looped; // make sure we only loop once + uint32 _handle; public: - PspRtc() : _startMillis(0), _startMicros(0), _lastMillis(0), _milliOffset(0), _looped(false) { init(); } - void init(); - uint32 getMillis(); - uint32 getMicros(); + PspSemaphore(int initialValue, int maxValue=255); + ~PspSemaphore(); + bool take() { return takeWithTimeOut(0); } + bool takeWithTimeOut(uint32 timeOut); + bool give(int num=1); + bool pollForValue(int value); // check for a certain value + int numOfWaitingThreads(); + int getValue(); +}; + +class PspMutex { +private: + PspSemaphore _semaphore; + int _recursiveCount; + int _ownerId; +public: + PspMutex(bool initialValue) : _semaphore(initialValue ? 1 : 0, 255), _recursiveCount(0), _ownerId(0) {} // initial, max value + bool lock(); + bool unlock(); + bool poll() { return _semaphore.pollForValue(1); } + int numOfWaitingThreads() { return _semaphore.numOfWaitingThreads(); } + bool getValue() { return (bool)_semaphore.getValue(); } +}; + +class PspCondition { +private: + PspMutex _mutex; + int _waitingThreads; + int _signaledThreads; + PspSemaphore _waitSem; + PspSemaphore _doneSem; +public: + PspCondition() : _mutex(true), _waitingThreads(0), _signaledThreads(0), + _waitSem(0), _doneSem(0) {} + void wait(PspMutex &externalMutex); + void releaseAll(); }; enum ThreadPriority { diff --git a/backends/platform/psp/trace.cpp b/backends/platform/psp/trace.cpp index 4bf5450177..7bac6534da 100644 --- a/backends/platform/psp/trace.cpp +++ b/backends/platform/psp/trace.cpp @@ -30,8 +30,9 @@ #include <stdio.h> int psp_debug_indent = 0; +bool firstWriteToFile = true; -void PSPDebugTrace(bool alsoToScreen, const char *format, ...) { +void PspDebugTrace(bool alsoToScreen, const char *format, ...) { va_list opt; char buffer[2048]; int bufsz; @@ -41,8 +42,12 @@ void PSPDebugTrace(bool alsoToScreen, const char *format, ...) { bufsz = vsnprintf(buffer, (size_t) sizeof(buffer), format, opt); va_end(opt); - //fd = fopen("MS0:/SCUMMTRACE.TXT", "ab"); - fd = fopen("SCUMMTRACE.TXT", "ab"); + if (firstWriteToFile) { + fd = fopen("SCUMMTRACE.TXT", "wb"); // erase the file the first time we write + firstWriteToFile = false; + } else { + fd = fopen("SCUMMTRACE.TXT", "ab"); + } if (fd == 0) return; diff --git a/backends/platform/psp/trace.h b/backends/platform/psp/trace.h index 1aad0f6781..ade8fd7214 100644 --- a/backends/platform/psp/trace.h +++ b/backends/platform/psp/trace.h @@ -39,8 +39,8 @@ #define __PSP_PRINT__(format,...) fprintf(stderr, format, ## __VA_ARGS__) #endif /* PSP_PRINT_TO_FILE/SCREEN */ -/* Error function */ -#define PSP_ERROR(format,...) __PSP_PRINT__("Error in %s: " format, __PRETTY_FUNCTION__, ## __VA_ARGS__) +/* Error function - always print to file as well */ +#define PSP_ERROR(format,...) PspDebugTrace(true, "Error in %s: " format, __PRETTY_FUNCTION__, ## __VA_ARGS__) /* Do the indent */ #define __PSP_INDENT__ for(int _i=psp_debug_indent; _i>0; _i--) \ @@ -52,7 +52,7 @@ #define PSP_INFO_PRINT_INDENT(format,...) { __PSP_INDENT__; \ __PSP_PRINT__(format, ## __VA_ARGS__); } -void PSPDebugTrace(bool alsoToScreen, const char *format, ...); +void PspDebugTrace(bool alsoToScreen, const char *format, ...); extern int psp_debug_indent; diff --git a/backends/platform/symbian/src/SymbianActions.cpp b/backends/platform/symbian/src/SymbianActions.cpp index d925f5f0e7..1a55a68778 100644 --- a/backends/platform/symbian/src/SymbianActions.cpp +++ b/backends/platform/symbian/src/SymbianActions.cpp @@ -28,6 +28,7 @@ #include "gui/message.h" #include "scumm/scumm.h" #include "common/config-manager.h" +#include "common/translation.h" #include <sdl.h> @@ -37,25 +38,25 @@ namespace GUI { // or we put them in this file separated by #ifdefs, this one is up to you, AnotherGuest :) const Common::String actionNames[] = { - "Up", - "Down", - "Left", - "Right", - "Left Click", - "Right Click", - "Save", - "Skip", - "Zone", - "Multi Function", - "Swap character", - "Skip text", - "Pause", - "Fast mode", - "Quit", - "Debugger", - "Global menu", - "Virtual keyboard", - "Key mapper" + _s("Up"), + _s("Down"), + _s("Left"), + _s("Right"), + _s("Left Click"), + _s("Right Click"), + _s("Save"), + _s("Skip"), + _s("Zone"), + _s("Multi Function"), + _s("Swap character"), + _s("Skip text"), + _s("Pause"), + _s("Fast mode"), + _s("Quit"), + _s("Debugger"), + _s("Global menu"), + _s("Virtual keyboard"), + _s("Key mapper") }; #ifdef UIQ @@ -75,7 +76,7 @@ void SymbianActions::init() { Common::String SymbianActions::actionName(ActionType action) { - return actionNames[action]; + return _(actionNames[action]); } int SymbianActions::size() { diff --git a/backends/platform/wii/options.cpp b/backends/platform/wii/options.cpp index a8f3552313..295856d564 100644 --- a/backends/platform/wii/options.cpp +++ b/backends/platform/wii/options.cpp @@ -28,6 +28,8 @@ #include "gui/dialog.h" #include "backends/fs/wii/wii-fs-factory.h" +#include "common/translation.h" + #include "options.h" WiiOptionsDialog::WiiOptionsDialog(bool doubleStrike) : @@ -42,84 +44,84 @@ WiiOptionsDialog::WiiOptionsDialog(bool doubleStrike) : _strUnderscanY = "wii_video_default_underscan_y"; } - new ButtonWidget(this, _w - 108 - 16, _h - 24 - 16, 108, 24, "Ok", 'k'); - new ButtonWidget(this, _w - 216 - 32, _h - 24 - 16, 108, 24, "Cancel", 'c'); + new ButtonWidget(this, _w - 108 - 16, _h - 24 - 16, 108, 24, _("OK"), 0, 'k'); + new ButtonWidget(this, _w - 216 - 32, _h - 24 - 16, 108, 24, _("Cancel"), 0, 'c'); _tab = new TabWidget(this, 0, 0, _w, _h - 54); - _tabVideo = _tab->addTab("Video"); + _tabVideo = _tab->addTab(_("Video")); new StaticTextWidget(_tab, 16, 16, 128, 16, - "Current video mode:", Graphics::kTextAlignRight); + _("Current video mode:"), Graphics::kTextAlignRight); new StaticTextWidget(_tab, 160, 16, 128, 16, - _doubleStrike ? "Double-strike" : "Default", + _doubleStrike ? _("Double-strike") : _("Default"), Graphics::kTextAlignLeft); new StaticTextWidget(_tab, 16, 48, 128, 16, - "Horizontal underscan:", Graphics::kTextAlignRight); - _sliderUnderscanX = new SliderWidget(_tab, 160, 47, 128, 18, 'x'); + _("Horizontal underscan:"), Graphics::kTextAlignRight); + _sliderUnderscanX = new SliderWidget(_tab, 160, 47, 128, 18, 0, 'x'); _sliderUnderscanX->setMinValue(0); _sliderUnderscanX->setMaxValue(32); new StaticTextWidget(_tab, 16, 80, 128, 16, - "Vertical underscan:", Graphics::kTextAlignRight); - _sliderUnderscanY = new SliderWidget(_tab, 160, 79, 128, 18, 'y'); + _("Vertical underscan:"), Graphics::kTextAlignRight); + _sliderUnderscanY = new SliderWidget(_tab, 160, 79, 128, 18, 0, 'y'); _sliderUnderscanY->setMinValue(0); _sliderUnderscanY->setMaxValue(32); - _tabInput = _tab->addTab("Input"); + _tabInput = _tab->addTab(_("Input")); new StaticTextWidget(_tab, 16, 16, 128, 16, - "GC Pad sensitivity:", Graphics::kTextAlignRight); - _sliderPadSensitivity = new SliderWidget(_tab, 160, 15, 128, 18, 'x'); + _("GC Pad sensitivity:"), Graphics::kTextAlignRight); + _sliderPadSensitivity = new SliderWidget(_tab, 160, 15, 128, 18, 0, 'x'); _sliderPadSensitivity->setMinValue(0); _sliderPadSensitivity->setMaxValue(64); new StaticTextWidget(_tab, 16, 44, 128, 16, - "GC Pad acceleration:", Graphics::kTextAlignRight); - _sliderPadAcceleration = new SliderWidget(_tab, 160, 43, 128, 18, 'y'); + _("GC Pad acceleration:"), Graphics::kTextAlignRight); + _sliderPadAcceleration = new SliderWidget(_tab, 160, 43, 128, 18, 0, 'y'); _sliderPadAcceleration->setMinValue(0); _sliderPadAcceleration->setMaxValue(8); #ifdef USE_WII_DI - _tabDVD = _tab->addTab("DVD"); + _tabDVD = _tab->addTab(_("DVD")); new StaticTextWidget(_tab, 16, 16, 64, 16, - "Status:", Graphics::kTextAlignRight); - _textDVDStatus = new StaticTextWidget(_tab, 96, 16, 272, 16, "Unknown", + _("Status:"), Graphics::kTextAlignRight); + _textDVDStatus = new StaticTextWidget(_tab, 96, 16, 272, 16, _("Unknown"), Graphics::kTextAlignLeft); - new ButtonWidget(_tab, 16, 48, 108, 24, "Mount DVD", 'mdvd'); - new ButtonWidget(_tab, 140, 48, 108, 24, "Unmount DVD", 'udvd'); + new ButtonWidget(_tab, 16, 48, 108, 24, _("Mount DVD"), 0, 'mdvd'); + new ButtonWidget(_tab, 140, 48, 108, 24, _("Unmount DVD"), 0, 'udvd'); #endif #ifdef USE_WII_SMB - _tabSMB = _tab->addTab("SMB"); + _tabSMB = _tab->addTab(_("SMB")); new StaticTextWidget(_tab, 16, 16, 64, 16, - "Status:", Graphics::kTextAlignRight); - _textSMBStatus = new StaticTextWidget(_tab, 96, 16, 272, 16, "Unknown", + _("Status:"), Graphics::kTextAlignRight); + _textSMBStatus = new StaticTextWidget(_tab, 96, 16, 272, 16, _("Unknown"), Graphics::kTextAlignLeft); new StaticTextWidget(_tab, 16, 52, 64, 16, - "Server:", Graphics::kTextAlignRight); + _("Server:"), Graphics::kTextAlignRight); _editSMBServer = new EditTextWidget(_tab, 96, 48, _w - 96 - 32, 24, ""); new StaticTextWidget(_tab, 16, 92, 64, 16, - "Share:", Graphics::kTextAlignRight); + _("Share:"), Graphics::kTextAlignRight); _editSMBShare = new EditTextWidget(_tab, 96, 88, _w - 96 - 32, 24, ""); new StaticTextWidget(_tab, 16, 132, 64, 16, - "Username:", Graphics::kTextAlignRight); + _("Username:"), Graphics::kTextAlignRight); _editSMBUsername = new EditTextWidget(_tab, 96, 128, _w - 96 - 32, 24, ""); new StaticTextWidget(_tab, 16, 172, 64, 16, - "Password:", Graphics::kTextAlignRight); + _("Password:"), Graphics::kTextAlignRight); _editSMBPassword = new EditTextWidget(_tab, 96, 168, _w - 96 - 32, 24, ""); - new ButtonWidget(_tab, 16, 208, 108, 24, "Init network", 'net'); + new ButtonWidget(_tab, 16, 208, 108, 24, _("Init network"), 0, 'net'); - new ButtonWidget(_tab, 140, 208, 108, 24, "Mount SMB", 'msmb'); - new ButtonWidget(_tab, 264, 208, 108, 24, "Unmount SMB", 'usmb'); + new ButtonWidget(_tab, 140, 208, 108, 24, _("Mount SMB"), 0, 'msmb'); + new ButtonWidget(_tab, 264, 208, 108, 24, _("Unmount SMB"), 0, 'usmb'); #endif _tab->setActiveTab(_tabVideo); @@ -140,12 +142,12 @@ void WiiOptionsDialog::handleTickle() { #ifdef USE_WII_DI if (tab == _tabDVD) { if (fsf.isMounted(WiiFilesystemFactory::kDVD)) { - _textDVDStatus->setLabel("DVD Mounted successfully"); + _textDVDStatus->setLabel(_("DVD Mounted successfully")); } else { if (fsf.failedToMount(WiiFilesystemFactory::kDVD)) - _textDVDStatus->setLabel("Error while mounting the DVD"); + _textDVDStatus->setLabel(_("Error while mounting the DVD")); else - _textDVDStatus->setLabel("DVD not mounted"); + _textDVDStatus->setLabel(_("DVD not mounted")); } } #endif @@ -158,32 +160,32 @@ void WiiOptionsDialog::handleTickle() { switch (status) { case 0: if (fsf.isMounted(WiiFilesystemFactory::kSMB)) { - label = "Network up, share mounted"; + label = _("Network up, share mounted"); } else { - label = "Network up"; + label = _("Network up"); if (fsf.failedToMount(WiiFilesystemFactory::kSMB)) - label += ", error while mounting the share"; + label += _(", error while mounting the share"); else - label += ", share not mounted"; + label += _(", share not mounted"); } break; case -ENETDOWN: - label = "Network down"; + label = _("Network down"); break; case -EBUSY: - label = "Initialising network"; + label = _("Initialising network"); break; case -ETIMEDOUT: - label = "Timeout while initialising network"; + label = _("Timeout while initialising network"); break; default: - label = String::printf("Network not initialsed (%d)", status); + label = String::printf(_("Network not initialsed (%d)"), status); break; } diff --git a/backends/platform/wii/osystem.h b/backends/platform/wii/osystem.h index d277aa38b1..8180d5727f 100644 --- a/backends/platform/wii/osystem.h +++ b/backends/platform/wii/osystem.h @@ -156,7 +156,7 @@ public: virtual bool setGraphicsMode(int mode); #ifdef USE_RGB_COLOR virtual Graphics::PixelFormat getScreenFormat() const; - virtual Common::List<Graphics::PixelFormat> getSupportedFormats(); + virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const; #endif virtual int getGraphicsMode() const; virtual void initSize(uint width, uint height, diff --git a/backends/platform/wii/osystem_gfx.cpp b/backends/platform/wii/osystem_gfx.cpp index 3d4e75883b..19190048a0 100644 --- a/backends/platform/wii/osystem_gfx.cpp +++ b/backends/platform/wii/osystem_gfx.cpp @@ -209,7 +209,7 @@ Graphics::PixelFormat OSystem_Wii::getScreenFormat() const { return _pfGame; } -Common::List<Graphics::PixelFormat> OSystem_Wii::getSupportedFormats() { +Common::List<Graphics::PixelFormat> OSystem_Wii::getSupportedFormats() const { Common::List<Graphics::PixelFormat> res; res.push_back(_pfRGB565); res.push_back(Graphics::PixelFormat::createFormatCLUT8()); diff --git a/backends/platform/wince/CEActionsPocket.cpp b/backends/platform/wince/CEActionsPocket.cpp index ebe6981290..64abd0be3e 100644 --- a/backends/platform/wince/CEActionsPocket.cpp +++ b/backends/platform/wince/CEActionsPocket.cpp @@ -31,30 +31,32 @@ #include "common/config-manager.h" #include "gui/KeysDialog.h" +#include "common/translation.h" + #ifdef _WIN32_WCE #define KEY_ALL_SKIP 3457 #endif const String pocketActionNames[] = { - "Pause", - "Save", - "Quit", - "Skip", - "Hide Toolbar", - "Show Keyboard", - "Sound on/off", - "Right click", - "Show/Hide Cursor", - "Free look", - "Zoom up", - "Zoom down", - "Multi Function", - "Bind Keys", - "Cursor Up", - "Cursor Down", - "Cursor Left", - "Cursor Right", - "Left Click", + _s("Pause"), + _s("Save"), + _s("Quit"), + _s("Skip"), + _s("Hide Toolbar"), + _s("Show Keyboard"), + _s("Sound on/off"), + _s("Right click"), + _s("Show/Hide Cursor"), + _s("Free look"), + _s("Zoom up"), + _s("Zoom down"), + _s("Multi Function"), + _s("Bind Keys"), + _s("Cursor Up"), + _s("Cursor Down"), + _s("Cursor Left"), + _s("Cursor Right"), + _s("Left Click") }; void CEActionsPocket::init() { @@ -63,7 +65,7 @@ void CEActionsPocket::init() { String CEActionsPocket::actionName(GUI::ActionType action) { - return pocketActionNames[action]; + return _(pocketActionNames[action]); } int CEActionsPocket::size() { @@ -258,7 +260,7 @@ bool CEActionsPocket::perform(GUI::ActionType action, bool pushed) { if (action == POCKET_ACTION_SAVE && ConfMan.get("gameid") == "parallaction") { // FIXME: This is a temporary solution. The engine should handle its own menus. // Note that the user can accomplish this via the virtual keyboard as well, this is just for convenience - GUI::MessageDialog alert("Do you want to load or save the game?", "Load", "Save"); + GUI::MessageDialog alert(_("Do you want to load or save the game?"), _("Load"), _("Save")); if (alert.runModal() == GUI::kMessageOK) _key_action[action].setKey(SDLK_l); else @@ -308,7 +310,7 @@ bool CEActionsPocket::perform(GUI::ActionType action, bool pushed) { case POCKET_ACTION_QUIT: if (!quitdialog) { quitdialog = true; - GUI::MessageDialog alert(" Are you sure you want to quit ? ", "Yes", "No"); + GUI::MessageDialog alert(_(" Are you sure you want to quit ? "), _("Yes"), _("No")); if (alert.runModal() == GUI::kMessageOK) _mainSystem->quit(); quitdialog = false; diff --git a/backends/platform/wince/CEActionsSmartphone.cpp b/backends/platform/wince/CEActionsSmartphone.cpp index 47733ae317..af80bd2908 100644 --- a/backends/platform/wince/CEActionsSmartphone.cpp +++ b/backends/platform/wince/CEActionsSmartphone.cpp @@ -30,23 +30,25 @@ #include "common/config-manager.h" #include "gui/KeysDialog.h" +#include "common/translation.h" + #define KEY_ALL_SKIP 3457 const String smartphoneActionNames[] = { - "Up", - "Down", - "Left", - "Right", - "Left Click", - "Right Click", - "Save", - "Skip", - "Zone", - "Multi Function", - "Bind Keys", - "Keyboard", - "Rotate", - "Quit" + _s("Up"), + _s("Down"), + _s("Left"), + _s("Right"), + _s("Left Click"), + _s("Right Click"), + _s("Save"), + _s("Skip"), + _s("Zone"), + _s("Multi Function"), + _s("Bind Keys"), + _s("Keyboard"), + _s("Rotate"), + _s("Quit") }; const int ACTIONS_SMARTPHONE_DEFAULT[] = { SDLK_UP, SDLK_DOWN, SDLK_LEFT, SDLK_RIGHT, SDLK_F1, SDLK_F2, SDLK_F3, SDLK_ESCAPE, SDLK_9, SDLK_8, SDLK_F4, SDLK_RETURN, SDLK_5, SDLK_0 }; @@ -57,7 +59,7 @@ void CEActionsSmartphone::init() { String CEActionsSmartphone::actionName(GUI::ActionType action) { - return smartphoneActionNames[action]; + return _(smartphoneActionNames[action]); } int CEActionsSmartphone::size() { @@ -220,7 +222,7 @@ bool CEActionsSmartphone::perform(GUI::ActionType action, bool pushed) { if (action == SMARTPHONE_ACTION_SAVE && ConfMan.get("gameid") == "parallaction") { // FIXME: This is a temporary solution. The engine should handle its own menus. // Note that the user can accomplish this via the virtual keyboard as well, this is just for convenience - GUI::MessageDialog alert("Do you want to load or save the game?", "Load", "Save"); + GUI::MessageDialog alert(_("Do you want to load or save the game?"), _("Load"), _("Save")); if (alert.runModal() == GUI::kMessageOK) _key_action[action].setKey(SDLK_l); else @@ -267,7 +269,7 @@ bool CEActionsSmartphone::perform(GUI::ActionType action, bool pushed) { case SMARTPHONE_ACTION_QUIT: if (!quitdialog) { quitdialog = true; - GUI::MessageDialog alert(" Are you sure you want to quit ? ", "Yes", "No"); + GUI::MessageDialog alert(_(" Are you sure you want to quit ? "), _("Yes"), _("No")); if (alert.runModal() == GUI::kMessageOK) _mainSystem->quit(); quitdialog = false; diff --git a/backends/platform/wince/CELauncherDialog.cpp b/backends/platform/wince/CELauncherDialog.cpp index 21a967336e..11e4900c2d 100644 --- a/backends/platform/wince/CELauncherDialog.cpp +++ b/backends/platform/wince/CELauncherDialog.cpp @@ -38,6 +38,8 @@ #include "common/config-manager.h" +#include "common/translation.h" + using namespace GUI; using namespace Common; @@ -51,13 +53,13 @@ public: // needs fixing, or remove it! const int buttonWidth = g_gui.xmlEval()->getVar("Globals.Button.Width", 0); const int buttonHeight = g_gui.xmlEval()->getVar("Globals.Button.Height", 0); - new ButtonWidget(this, (_w - buttonWidth) / 2, 45, buttonWidth, buttonHeight, "OK", kCloseCmd, '\r'); // Close dialog - FIXME + new ButtonWidget(this, (_w - buttonWidth) / 2, 45, buttonWidth, buttonHeight, _("OK"), 0, kCloseCmd, '\r'); // Close dialog - FIXME - Common::String videoDriver("Using SDL driver "); + Common::String videoDriver(_("Using SDL driver ")); SDL_VideoDriverName(tempo, sizeof(tempo)); videoDriver += tempo; new StaticTextWidget(this, 0, 10, _w, kLineHeight, videoDriver, Graphics::kTextAlignCenter); - Common::String displayInfos("Display "); + Common::String displayInfos(_("Display ")); sprintf(tempo, "%dx%d (real %dx%d)", GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), OSystem_WINCE3::getScreenWidth(), OSystem_WINCE3::getScreenHeight()); displayInfos += tempo; new StaticTextWidget(this, 0, 20, _w, kLineHeight, displayInfos, Graphics::kTextAlignCenter); @@ -99,7 +101,7 @@ void CELauncherDialog::automaticScanDirectory(const Common::FSNode &node) { * returns some illegal paths atm. */ void CELauncherDialog::addGame() { - MessageDialog alert("Do you want to perform an automatic scan ?", "Yes", "No"); + MessageDialog alert(_("Do you want to perform an automatic scan ?"), _("Yes"), _("No")); if (alert.runModal() == kMessageOK && _browser->runModal() > 0) { // Clear existing domains ConfigManager::DomainMap &domains = (ConfigManager::DomainMap&)ConfMan.getGameDomains(); diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp index b3480702b5..aef2117bd7 100644 --- a/backends/platform/wince/wince-sdl.cpp +++ b/backends/platform/wince/wince-sdl.cpp @@ -30,6 +30,7 @@ #include "common/events.h" #include "common/util.h" #include "common/timer.h" +#include "common/translation.h" #include "engines/engine.h" @@ -107,14 +108,14 @@ bool _hasSmartphoneResolution = false; // Low end devices 240x320 static const OSystem::GraphicsMode s_supportedGraphicsModesLow[] = { - {"1x", "Normal (no scaling)", GFX_NORMAL}, + {"1x", _s("Normal (no scaling)"), GFX_NORMAL}, {0, 0, 0} }; // High end device 480x640 static const OSystem::GraphicsMode s_supportedGraphicsModesHigh[] = { - {"1x", "Normal (no scaling)", GFX_NORMAL}, + {"1x", _s("Normal (no scaling)"), GFX_NORMAL}, {"2x", "2x", GFX_DOUBLESIZE}, #ifndef _MSC_VER // EVC breaks template functions, and I'm tired of fixing them :) {"2xsai", "2xSAI", GFX_2XSAI}, @@ -2263,6 +2264,7 @@ static int mapKeyCE(SDLKey key, SDLMod mod, Uint16 unicode, bool unfilter) { bool OSystem_WINCE3::pollEvent(Common::Event &event) { SDL_Event ev; + ev.type = SDL_NOEVENT; byte b = 0; DWORD currentTime; bool keyEvent = false; diff --git a/backends/plugins/psp/psp-provider.cpp b/backends/plugins/psp/psp-provider.cpp index f394916538..5760424cbf 100644 --- a/backends/plugins/psp/psp-provider.cpp +++ b/backends/plugins/psp/psp-provider.cpp @@ -31,6 +31,8 @@ #include "backends/platform/psp/psploader.h" +#include "backends/platform/psp/trace.h" + class PSPPlugin : public DynamicPlugin { protected: @@ -95,13 +97,13 @@ Plugin* PSPPluginProvider::createPlugin(const Common::FSNode &node) const { bool PSPPluginProvider::isPluginFilename(const Common::FSNode &node) const { // Check the plugin suffix Common::String filename = node.getName(); - fprintf(stderr, "Testing name %s", filename.c_str()); + PSP_DEBUG_PRINT("Testing name %s", filename.c_str()); if (!filename.hasSuffix(".PLG") && !filename.hasSuffix(".plg")) { - fprintf(stderr," fail.\n"); + PSP_DEBUG_PRINT(" fail.\n"); return false; } - fprintf(stderr," success!\n"); + PSP_DEBUG_PRINT(" success!\n"); return true; } diff --git a/backends/plugins/win32/win32-provider.cpp b/backends/plugins/win32/win32-provider.cpp index a39bdfe76a..65586249e8 100644 --- a/backends/plugins/win32/win32-provider.cpp +++ b/backends/plugins/win32/win32-provider.cpp @@ -30,6 +30,7 @@ #include "common/debug.h" #include "common/fs.h" +#define WIN32_LEAN_AND_MEAN #include <windows.h> diff --git a/backends/vkeybd/virtual-keyboard.cpp b/backends/vkeybd/virtual-keyboard.cpp index bd512fe3ad..2c88322191 100644 --- a/backends/vkeybd/virtual-keyboard.cpp +++ b/backends/vkeybd/virtual-keyboard.cpp @@ -90,7 +90,6 @@ bool VirtualKeyboard::openPack(const String &packName, const FSNode &node) { return true; } -#ifdef USE_ZLIB if (node.getChild(packName + ".zip").exists()) { // compressed keyboard pack _fileArchive = makeZipArchive(node.getChild(packName + ".zip")); @@ -109,7 +108,6 @@ bool VirtualKeyboard::openPack(const String &packName, const FSNode &node) { return true; } -#endif return false; } diff --git a/base/commandLine.cpp b/base/commandLine.cpp index 1c548d3f50..e795b82d0a 100644 --- a/base/commandLine.cpp +++ b/base/commandLine.cpp @@ -32,8 +32,6 @@ #include "common/system.h" #include "common/fs.h" -#include "sound/mididrv.h" - #include "gui/ThemeEngine.h" #define DETECTOR_TESTING_HACK @@ -61,7 +59,7 @@ static const char HELP_STRING[] = " -h, --help Display a brief help text and exit\n" " -z, --list-games Display list of supported games and exit\n" " -t, --list-targets Display list of configured targets and exit\n" - " --list-saves=TARGET Display a list of savegames for the game (TARGET) specified\n" + " --list-saves=TARGET Display a list of savegames for the game (TARGET) specified\n" "\n" " -c, --config=CONFIG Use alternate configuration file\n" " -p, --path=PATH Path to where the game is installed\n" @@ -364,8 +362,6 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha END_OPTION DO_OPTION('e', "music-driver") - if (MidiDriver::findMusicDriver(option) == 0) - usage("Unrecognized music driver '%s'", option); END_OPTION DO_LONG_OPTION_INT("output-rate") diff --git a/base/internal_version.h b/base/internal_version.h index bdd0474c2b..2e6b7a24ad 100644 --- a/base/internal_version.h +++ b/base/internal_version.h @@ -2,4 +2,9 @@ #define SCUMMVM_SVN_REVISION #endif +#ifdef RELEASE_BUILD +#undef SCUMMVM_SVN_REVISION +#define SCUMMVM_SVN_REVISION +#endif + #define SCUMMVM_VERSION "1.2.0svn" SCUMMVM_SVN_REVISION diff --git a/base/internal_version.h.in b/base/internal_version.h.in index 1b7e5ed147..4eecf90d87 100644 --- a/base/internal_version.h.in +++ b/base/internal_version.h.in @@ -2,4 +2,9 @@ #define SCUMMVM_SVN_REVISION #endif +#ifdef RELEASE_BUILD +#undef SCUMMVM_SVN_REVISION +#define SCUMMVM_SVN_REVISION +#endif + #define SCUMMVM_VERSION "@VERSION@" SCUMMVM_SVN_REVISION diff --git a/base/main.cpp b/base/main.cpp index 7f3b9467b3..477f2afcb1 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -47,11 +47,14 @@ #include "common/fs.h" #include "common/system.h" #include "common/tokenizer.h" +#include "common/translation.h" #include "gui/GuiManager.h" #include "gui/message.h" #include "gui/error.h" +#include "sound/mididrv.h" + #include "backends/keymapper/keymapper.h" #if defined(_WIN32_WCE) @@ -100,7 +103,7 @@ static const EnginePlugin *detectPlugin() { // Query the plugins and find one that will handle the specified gameid printf("User picked target '%s' (gameid '%s')...\n", ConfMan.getActiveDomainName().c_str(), gameid.c_str()); - printf(" Looking for a plugin supporting this gameid... "); + printf("%s", " Looking for a plugin supporting this gameid... "); GameDescriptor game = EngineMan.findGame(gameid, &plugin); if (plugin == 0) { @@ -139,7 +142,7 @@ static Common::Error runGame(const EnginePlugin *plugin, OSystem &system, const // Is a separate dialog here still required? //GUI::displayErrorDialog("ScummVM could not find any game in the specified directory!"); - const char *errMsg = Common::errorToString(err); + const char *errMsg = _(Common::errorToString(err)); warning("%s failed to instantiate engine: %s (target '%s', path '%s')", plugin->getName(), @@ -198,7 +201,7 @@ static Common::Error runGame(const EnginePlugin *plugin, OSystem &system, const while (!tokenizer.empty()) { Common::String token = tokenizer.nextToken(); if (!DebugMan.enableDebugChannel(token)) - warning("Engine does not support debug level '%s'", token.c_str()); + warning(_("Engine does not support debug level '%s'"), token.c_str()); } // Inform backend that the engine is about to be run @@ -266,22 +269,22 @@ static void setupKeymapper(OSystem &system) { mapper->registerHardwareKeySet(keySet); // Now create the global keymap - act = new Action(globalMap, "MENU", "Menu", kGenericActionType, kSelectKeyType); + act = new Action(globalMap, "MENU", _("Menu"), kGenericActionType, kSelectKeyType); act->addKeyEvent(KeyState(KEYCODE_F5, ASCII_F5, 0)); - act = new Action(globalMap, "SKCT", "Skip", kGenericActionType, kActionKeyType); + act = new Action(globalMap, "SKCT", _("Skip"), kGenericActionType, kActionKeyType); act->addKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE, 0)); - act = new Action(globalMap, "PAUS", "Pause", kGenericActionType, kStartKeyType); + act = new Action(globalMap, "PAUS", _("Pause"), kGenericActionType, kStartKeyType); act->addKeyEvent(KeyState(KEYCODE_SPACE, ' ', 0)); - act = new Action(globalMap, "SKLI", "Skip line", kGenericActionType, kActionKeyType); + act = new Action(globalMap, "SKLI", _("Skip line"), kGenericActionType, kActionKeyType); act->addKeyEvent(KeyState(KEYCODE_PERIOD, '.', 0)); - act = new Action(globalMap, "VIRT", "Display keyboard", kVirtualKeyboardActionType); + act = new Action(globalMap, "VIRT", _("Display keyboard"), kVirtualKeyboardActionType); act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0)); - act = new Action(globalMap, "REMP", "Remap keys", kKeyRemapActionType); + act = new Action(globalMap, "REMP", _("Remap keys"), kKeyRemapActionType); act->addKeyEvent(KeyState(KEYCODE_F8, ASCII_F8, 0)); mapper->addGlobalKeymap(globalMap); @@ -317,6 +320,8 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) { // Update the config file ConfMan.set("versioninfo", gScummVMVersion, Common::ConfigManager::kApplicationDomain); + // Enable translation + TransMan.setLanguage(ConfMan.get("gui_language").c_str()); // Load and setup the debuglevel and the debug flags. We do this at the // soonest possible moment to ensure debug output starts early on, if @@ -336,6 +341,16 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) { // Load the plugins. PluginManager::instance().loadPlugins(); + // If we received an invalid music parameter via command line we check this here. + // We can't check this before loading the music plugins. + // On the other hand we cannot load the plugins before we know the file paths (in case of external plugins). + if (settings.contains("music-driver")) { + if (MidiDriver::getMusicType(MidiDriver::getDeviceHandle(settings["music-driver"])) == MT_INVALID) { + warning("Unrecognized music driver '%s'. Switching to default device.", settings["music-driver"].c_str()); + settings["music-driver"] = "auto"; + } + } + // Process the remaining command line settings. Must be done after the // config file and the plugins have been loaded. Common::Error res; @@ -385,7 +400,7 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) { // Did an error occur ? if (result != Common::kNoError) { // Shows an informative error dialog if starting the selected game failed. - GUI::displayErrorDialog(result, "Error running game:"); + GUI::displayErrorDialog(result, _("Error running game:")); } // Quit unless an error occurred, or Return to launcher was requested @@ -411,8 +426,8 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) { } else { // A dialog would be nicer, but we don't have any // screen to draw on yet. - warning("Could not find any engine capable of running the selected game"); - GUI::displayErrorDialog("Could not find any engine capable of running the selected game"); + warning("%s", _("Could not find any engine capable of running the selected game")); + GUI::displayErrorDialog(_("Could not find any engine capable of running the selected game")); } // reset the graphics to default diff --git a/base/plugins.cpp b/base/plugins.cpp index 6c80da65d4..a6acd7e449 100644 --- a/base/plugins.cpp +++ b/base/plugins.cpp @@ -167,6 +167,7 @@ public: // Music plugins // TODO: Use defines to disable or enable each MIDI driver as a // static/dynamic plugin, like it's done for the engines + LINK_PLUGIN(AUTO) LINK_PLUGIN(NULL) #if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) LINK_PLUGIN(WINDOWS) @@ -174,7 +175,7 @@ public: #if defined(UNIX) && defined(USE_ALSA) LINK_PLUGIN(ALSA) #endif - #if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__) && !defined(__MINT__) + #if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__) && !defined(__MINT__) && !defined(__ANDROID__) LINK_PLUGIN(SEQ) #endif #if defined(__MINT__) @@ -204,6 +205,8 @@ public: LINK_PLUGIN(MT32) #endif LINK_PLUGIN(ADLIB) + LINK_PLUGIN(PCSPK) + LINK_PLUGIN(PCJR) LINK_PLUGIN(TOWNS) #if defined (UNIX) LINK_PLUGIN(TIMIDITY) diff --git a/common/config-file.cpp b/common/config-file.cpp index cc55ebd6c7..d001a66c9e 100644 --- a/common/config-file.cpp +++ b/common/config-file.cpp @@ -125,7 +125,7 @@ bool ConfigFile::loadFromStream(SeekableReadStream &stream) { if (*p == '\0') error("ConfigFile::loadFromStream: missing ] in line %d", lineno); else if (*p != ']') - error("ConfigFile::loadFromStream: Invalid character '%c' occured in section name in line %d", *p, lineno); + error("ConfigFile::loadFromStream: Invalid character '%c' occurred in section name in line %d", *p, lineno); // Previous section is finished now, store it. if (!section.name.empty()) diff --git a/common/error.cpp b/common/error.cpp index d51774fd3e..6d1e349287 100644 --- a/common/error.cpp +++ b/common/error.cpp @@ -26,6 +26,8 @@ #include "common/error.h" #include "common/util.h" +#include "common/translation.h" + namespace Common { /** @@ -38,24 +40,24 @@ struct ErrorMessage { }; static const ErrorMessage _errMsgTable[] = { - { kInvalidPathError, "Invalid Path" }, - { kNoGameDataFoundError, "Game Data not found" }, - { kUnsupportedGameidError, "Game Id not supported" }, - { kUnsupportedColorMode, "Unsupported Color Mode" }, + { kInvalidPathError, _s("Invalid Path") }, + { kNoGameDataFoundError, _s("Game Data not found") }, + { kUnsupportedGameidError, _s("Game Id not supported") }, + { kUnsupportedColorMode, _s("Unsupported Color Mode") }, - { kReadPermissionDenied, "Read permission denied" }, - { kWritePermissionDenied, "Write permission denied" }, + { kReadPermissionDenied, _s("Read permission denied") }, + { kWritePermissionDenied, _s("Write permission denied") }, // The following three overlap a bit with kInvalidPathError and each other. Which to keep? - { kPathDoesNotExist, "Path not exists" }, - { kPathNotDirectory, "Path not a directory" }, - { kPathNotFile, "Path not a file" }, + { kPathDoesNotExist, _s("Path not exists") }, + { kPathNotDirectory, _s("Path not a directory") }, + { kPathNotFile, _s("Path not a file") }, - { kCreatingFileFailed, "Cannot create file" }, - { kReadingFailed, "Reading failed" }, - { kWritingFailed, "Writing data failed" }, + { kCreatingFileFailed, _s("Cannot create file") }, + { kReadingFailed, _s("Reading failed") }, + { kWritingFailed, _s("Writing data failed") }, - { kUnknownError, "Unknown Error" } + { kUnknownError, _s("Unknown Error") } }; const char *errorToString(Error error) { @@ -66,7 +68,7 @@ const char *errorToString(Error error) { } } - return "Unknown Error"; + return _("Unknown Error"); } } // End of namespace Common diff --git a/common/error.h b/common/error.h index 7aff8d40b9..58343114a2 100644 --- a/common/error.h +++ b/common/error.h @@ -44,7 +44,7 @@ namespace Common { * kPathInvalid, kPathIsInvalid, kInvalidPathError */ enum Error { - kNoError = 0, ///< No error occured + kNoError = 0, ///< No error occurred kInvalidPathError, ///< Engine initialization: Invalid game path was passed kNoGameDataFoundError, ///< Engine initialization: No game data was found in the specified location kUnsupportedGameidError, ///< Engine initialization: Gameid not supported by this (Meta)Engine diff --git a/common/events.h b/common/events.h index 24c9a23728..3c4f6e8d1c 100644 --- a/common/events.h +++ b/common/events.h @@ -201,13 +201,14 @@ public: * Notifies the observer of an incoming event. * * An observer is supposed to eat the event, with returning true, when - * it might want prevent other observers from preventing to receive - * the event. An usage example here is the keymapper: + * it wants to prevent other observers from receiving the event. + * An usage example here is the keymapper: * If it processes an Event, it should 'eat' it and create a new * event, which the EventDispatcher will then catch. * - * @param event the event, which is incoming. - * @return true if this observer uses this event, false otherwise. + * @param event the event, which is incoming. + * @return true if the event should not be passed to other observers, + * false otherwise. */ virtual bool notifyEvent(const Event &event) = 0; }; diff --git a/common/file.cpp b/common/file.cpp index 6291aa8855..dec0f2a953 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -51,11 +51,11 @@ bool File::open(const String &filename, Archive &archive) { SeekableReadStream *stream = 0; if ((stream = archive.createReadStreamForMember(filename))) { - debug(3, "Opening hashed: %s", filename.c_str()); + debug(8, "Opening hashed: %s", filename.c_str()); } else if ((stream = archive.createReadStreamForMember(filename + "."))) { // WORKAROUND: Bug #1458388: "SIMON1: Game Detection fails" // sometimes instead of "GAMEPC" we get "GAMEPC." (note trailing dot) - debug(3, "Opening hashed: %s.", filename.c_str()); + debug(8, "Opening hashed: %s.", filename.c_str()); } return open(stream, filename); diff --git a/common/macresman.cpp b/common/macresman.cpp index 6a6a818083..df7351d55a 100644 --- a/common/macresman.cpp +++ b/common/macresman.cpp @@ -525,12 +525,10 @@ void MacResManager::convertCrsrCursor(byte *data, int datasize, byte **cursor, i int i, b; byte imageByte; byte *iconData; - int numBytes; int pixelsPerByte, bpp; int ctSize; byte bitmask; int iconRowBytes, iconBounds[4]; - int ignored; int iconDataSize; dis.readUint16BE(); // type @@ -616,21 +614,19 @@ void MacResManager::convertCrsrCursor(byte *data, int datasize, byte **cursor, i dis.readUint16BE(); // colorID[c] palette[0][c * 4 + 0] = dis.readByte(); - ignored = dis.readByte(); + dis.readByte(); palette[0][c * 4 + 1] = dis.readByte(); - ignored = dis.readByte(); + dis.readByte(); palette[0][c * 4 + 2] = dis.readByte(); - ignored = dis.readByte(); + dis.readByte(); palette[0][c * 4 + 3] = 0; } *palSize = ctSize; - numBytes = (iconBounds[2] - iconBounds[0]) * (iconBounds[3] - iconBounds[1]); - pixelsPerByte = (iconBounds[2] - iconBounds[0]) / iconRowBytes; bpp = 8 / pixelsPerByte; diff --git a/common/messages.cpp b/common/messages.cpp new file mode 100644 index 0000000000..fe87b5f642 --- /dev/null +++ b/common/messages.cpp @@ -0,0 +1,2063 @@ +// generated by po2c 1.0.2-scummvm - Do not modify + +static const char * const _messageIds[] = { + /* 0 */ "", + /* 1 */ " Are you sure you want to quit ? ", + /* 2 */ " (Active)", + /* 3 */ " (Game)", + /* 4 */ " (Global)", + /* 5 */ "(built on %s)", + /* 6 */ ", error while mounting the share", + /* 7 */ ", share not mounted", + /* 8 */ "... progress ...", + /* 9 */ "11kHz", + /* 10 */ "22 kHz", + /* 11 */ "44 kHz", + /* 12 */ "48 kHz", + /* 13 */ "8 kHz", + /* 14 */ "<default>", + /* 15 */ "About ScummVM", + /* 16 */ "AdLib Emulator", + /* 17 */ "AdLib emulator:", + /* 18 */ "AdLib is used for music in many games", + /* 19 */ "Add Game...", + /* 20 */ "Antialiased Renderer (16bpp)", + /* 21 */ "Aspect ratio correction", + /* 22 */ "Associated key : %s", + /* 23 */ "Associated key : none", + /* 24 */ "Audio", + /* 25 */ "Autosave:", + /* 26 */ "Available engines:", + /* 27 */ "A~b~out...", + /* 28 */ "Bind Keys", + /* 29 */ "Both", + /* 30 */ "Brightness:", + /* 31 */ "Cancel", + /* 32 */ "Cannot create file", + /* 33 */ "Change game options", + /* 34 */ "Change global ScummVM options", + /* 35 */ "Check if you want to use your real hardware Roland-compatible sound device connected to your computer", + /* 36 */ "Choose", + /* 37 */ "Choose an action to map", + /* 38 */ "Clear value", + /* 39 */ "Close", + /* 40 */ "Correct aspect ratio for 320x200 games", + /* 41 */ "Could not find any engine capable of running the selected game", + /* 42 */ "Current video mode:", + /* 43 */ "Cursor Down", + /* 44 */ "Cursor Left", + /* 45 */ "Cursor Right", + /* 46 */ "Cursor Up", + /* 47 */ "DOSBox OPL emulator", + /* 48 */ "DVD", + /* 49 */ "DVD Mounted successfully", + /* 50 */ "DVD not mounted", + /* 51 */ "Date: ", + /* 52 */ "Debugger", + /* 53 */ "Default", + /* 54 */ "Delete", + /* 55 */ "Disable power off", + /* 56 */ "Disabled GFX", + /* 57 */ "Discovered %d new games ...", + /* 58 */ "Discovered %d new games.", + /* 59 */ "Display ", + /* 60 */ "Display keyboard", + /* 61 */ "Do you really want to delete this savegame?", + /* 62 */ "Do you really want to remove this game configuration?", + /* 63 */ "Do you really want to run the mass game detector? This could potentially add a huge number of games.", + /* 64 */ "Do you want to load or save the game?", + /* 65 */ "Do you want to perform an automatic scan ?", + /* 66 */ "Do you want to quit ?", + /* 67 */ "Double-strike", + /* 68 */ "Down", + /* 69 */ "Enable Roland GS Mode", + /* 70 */ "Engine does not support debug level '%s'", + /* 71 */ "English", + /* 72 */ "Error running game:", + /* 73 */ "Error while mounting the DVD", + /* 74 */ "Extra Path:", + /* 75 */ "FM Towns Emulator", + /* 76 */ "Fast mode", + /* 77 */ "Features compiled in:", + /* 78 */ "Free look", + /* 79 */ "Full title of the game", + /* 80 */ "Fullscreen mode", + /* 81 */ "GC Pad acceleration:", + /* 82 */ "GC Pad sensitivity:", + /* 83 */ "GFX", + /* 84 */ "GM Device:", + /* 85 */ "GUI Language:", + /* 86 */ "GUI Renderer:", + /* 87 */ "Game", + /* 88 */ "Game Data not found", + /* 89 */ "Game Id not supported", + /* 90 */ "Game Path:", + /* 91 */ "Global menu", + /* 92 */ "Go to previous directory level", + /* 93 */ "Go up", + /* 94 */ "Graphics", + /* 95 */ "Graphics mode:", + /* 96 */ "Hardware scale (fast, but low quality)", + /* 97 */ "Hercules Amber", + /* 98 */ "Hercules Green", + /* 99 */ "Hide Toolbar", + /* 100 */ "High quality audio (slower) (reboot)", + /* 101 */ "Higher value specifies better sound quality but may be not supported by your soundcard", + /* 102 */ "Hold Shift for Mass Add", + /* 103 */ "Horizontal underscan:", + /* 104 */ "IBM PCjr Emulator", + /* 105 */ "ID:", + /* 106 */ "Init network", + /* 107 */ "Initial top screen scale:", + /* 108 */ "Initialising MT-32 Emulator", + /* 109 */ "Initialising network", + /* 110 */ "Input", + /* 111 */ "Invalid Path", + /* 112 */ "Key mapper", + /* 113 */ "Keyboard", + /* 114 */ "Keymap:", + /* 115 */ "Keys", + /* 116 */ "Language of ScummVM GUI", + /* 117 */ "Language of the game. This will not turn your Spanish game version into English", + /* 118 */ "Language:", + /* 119 */ "Left", + /* 120 */ "Left Click", + /* 121 */ "Load", + /* 122 */ "Load game:", + /* 123 */ "Load savegame for selected game", + /* 124 */ "MAME OPL emulator", + /* 125 */ "MIDI", + /* 126 */ "MIDI gain:", + /* 127 */ "MT-32 Device:", + /* 128 */ "MT-32 Emulator", + /* 129 */ "Main screen scaling:", + /* 130 */ "Map", + /* 131 */ "Mass Add...", + /* 132 */ "Menu", + /* 133 */ "Misc", + /* 134 */ "Mixed AdLib/MIDI mode", + /* 135 */ "Mount DVD", + /* 136 */ "Mount SMB", + /* 137 */ "Mouse click", + /* 138 */ "Multi Function", + /* 139 */ "Music Device:", + /* 140 */ "Music volume:", + /* 141 */ "Mute All", + /* 142 */ "Name:", + /* 143 */ "Network down", + /* 144 */ "Network not initialsed (%d)", + /* 145 */ "Network up", + /* 146 */ "Network up, share mounted", + /* 147 */ "Never", + /* 148 */ "No", + /* 149 */ "No date saved", + /* 150 */ "No music", + /* 151 */ "No playtime saved", + /* 152 */ "No time saved", + /* 153 */ "None", + /* 154 */ "Normal (no scaling)", + /* 155 */ "OK", + /* 156 */ "Output rate:", + /* 157 */ "Override global MIDI settings", + /* 158 */ "Override global audio settings", + /* 159 */ "Override global graphic settings", + /* 160 */ "Override global volume settings", + /* 161 */ "PC Speaker Emulator", + /* 162 */ "Password:", + /* 163 */ "Path not a directory", + /* 164 */ "Path not a file", + /* 165 */ "Path not exists", + /* 166 */ "Paths", + /* 167 */ "Pause", + /* 168 */ "Pick the game:", + /* 169 */ "Platform the game was originally designed for", + /* 170 */ "Platform:", + /* 171 */ "Playtime: ", + /* 172 */ "Please select an action", + /* 173 */ "Plugins Path:", + /* 174 */ "Preferred Device:", + /* 175 */ "Press the key to associate", + /* 176 */ "Quit", + /* 177 */ "Quit ScummVM", + /* 178 */ "Read permission denied", + /* 179 */ "Reading failed", + /* 180 */ "Remap keys", + /* 181 */ "Remove game from the list. The game data files stay intact", + /* 182 */ "Render mode:", + /* 183 */ "Right", + /* 184 */ "Right Click", + /* 185 */ "Right click", + /* 186 */ "Rotate", + /* 187 */ "SFX volume:", + /* 188 */ "SMB", + /* 189 */ "Save", + /* 190 */ "Save Path:", + /* 191 */ "Save Path: ", + /* 192 */ "Save game:", + /* 193 */ "Scan complete!", + /* 194 */ "Scanned %d directories ...", + /* 195 */ "ScummVM Main Menu", + /* 196 */ "ScummVM could not find any engine capable of running the selected game!", + /* 197 */ "ScummVM could not find any game in the specified directory!", + /* 198 */ "ScummVM couldn't open the specified directory!", + /* 199 */ "Search in game list", + /* 200 */ "Search:", + /* 201 */ "Select SoundFont", + /* 202 */ "Select a Theme", + /* 203 */ "Select additional game directory", + /* 204 */ "Select an action and click 'Map'", + /* 205 */ "Select directory for GUI themes", + /* 206 */ "Select directory for extra files", + /* 207 */ "Select directory for plugins", + /* 208 */ "Select directory for saved games", + /* 209 */ "Select directory for savegames", + /* 210 */ "Select directory with game data", + /* 211 */ "Sensitivity", + /* 212 */ "Server:", + /* 213 */ "Share:", + /* 214 */ "Short game identifier used for referring to savegames and running the game from the command line", + /* 215 */ "Show Keyboard", + /* 216 */ "Show mouse cursor", + /* 217 */ "Show subtitles and play speech", + /* 218 */ "Show/Hide Cursor", + /* 219 */ "Skip", + /* 220 */ "Skip line", + /* 221 */ "Skip text", + /* 222 */ "Snap to edges", + /* 223 */ "Software scale (good quality, but slower)", + /* 224 */ "Sound on/off", + /* 225 */ "SoundFont is supported by some audio cards, Fluidsynth and Timidity", + /* 226 */ "SoundFont:", + /* 227 */ "Spch", + /* 228 */ "Special dithering modes supported by some games", + /* 229 */ "Special sound effects volume", + /* 230 */ "Specifies default sound device for General MIDI output", + /* 231 */ "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output", + /* 232 */ "Specifies output sound device or sound card emulator", + /* 233 */ "Specifies path to additional data used by all games or ScummVM", + /* 234 */ "Specifies path to additional data used the game", + /* 235 */ "Specifies preferred sound device or sound card emulator", + /* 236 */ "Specifies where your savegames are put", + /* 237 */ "Speech", + /* 238 */ "Speech volume:", + /* 239 */ "Standard Renderer (16bpp)", + /* 240 */ "Start selected game", + /* 241 */ "Status:", + /* 242 */ "Subs", + /* 243 */ "Subtitle speed:", + /* 244 */ "Subtitles", + /* 245 */ "Swap character", + /* 246 */ "Tap for left click, double tap right click", + /* 247 */ "Text and Speech:", + /* 248 */ "The chosen directory cannot be written to. Please select another one.", + /* 249 */ "Theme Path:", + /* 250 */ "Theme:", + /* 251 */ "This game ID is already taken. Please choose another one.", + /* 252 */ "This game does not support loading games from the launcher.", + /* 253 */ "Time: ", + /* 254 */ "Timeout while initialising network", + /* 255 */ "Touch X Offset", + /* 256 */ "Touch Y Offset", + /* 257 */ "Touchpad mode disabled.", + /* 258 */ "Touchpad mode enabled.", + /* 259 */ "True Roland MT-32 (disable GM emulation)", + /* 260 */ "Turns off General MIDI mapping for games with Roland MT-32 soundtrack", + /* 261 */ "Unknown", + /* 262 */ "Unknown Error", + /* 263 */ "Unmount DVD", + /* 264 */ "Unmount SMB", + /* 265 */ "Unscaled (you must scroll left and right)", + /* 266 */ "Unsupported Color Mode", + /* 267 */ "Untitled savestate", + /* 268 */ "Up", + /* 269 */ "Use both MIDI and AdLib sound generation", + /* 270 */ "Use laptop trackpad-style cursor control", + /* 271 */ "Username:", + /* 272 */ "Using SDL driver ", + /* 273 */ "Vertical underscan:", + /* 274 */ "Video", + /* 275 */ "Virtual keyboard", + /* 276 */ "Volume", + /* 277 */ "Windows MIDI", + /* 278 */ "Write permission denied", + /* 279 */ "Writing data failed", + /* 280 */ "Yes", + /* 281 */ "You have to restart ScummVM to take the effect.", + /* 282 */ "Zone", + /* 283 */ "Zoom down", + /* 284 */ "Zoom up", + /* 285 */ "every 10 mins", + /* 286 */ "every 15 mins", + /* 287 */ "every 30 mins", + /* 288 */ "every 5 mins", + /* 289 */ "~A~bout", + /* 290 */ "~A~dd Game...", + /* 291 */ "~C~ancel", + /* 292 */ "~C~lose", + /* 293 */ "~E~dit Game...", + /* 294 */ "~H~elp", + /* 295 */ "~I~ndy fight controls", + /* 296 */ "~K~eys", + /* 297 */ "~L~eft handed mode", + /* 298 */ "~L~oad", + /* 299 */ "~L~oad...", + /* 300 */ "~N~ext", + /* 301 */ "~O~K", + /* 302 */ "~O~ptions", + /* 303 */ "~O~ptions...", + /* 304 */ "~P~revious", + /* 305 */ "~Q~uit", + /* 306 */ "~R~emove Game", + /* 307 */ "~R~esume", + /* 308 */ "~R~eturn to Launcher", + /* 309 */ "~S~ave", + /* 310 */ "~S~tart", + /* 311 */ "~T~ransitions Enabled", + /* 312 */ "~W~ater Effect Enabled", + /* 313 */ "~Z~ip Mode Activated", + NULL +}; + +struct PoMessageEntry { + int msgid; + const char *msgstr; +}; + +static const PoMessageEntry _translation_ru_RU[] = { + { 0, "Project-Id-Version: ScummVM VERSION\nReport-Msgid-Bugs-To: scummvm-devel@lists.sf.net\nPOT-Creation-Date: 2010-07-12 17:44+0200\nPO-Revision-Date: 2010-06-13 20:55+0300\nLast-Translator: Eugene Sandulenko <sev@scummvm.org>\nLanguage-Team: Russian\nLanguage: \nMIME-Version: 1.0\nContent-Type: text/plain; charset=iso-8859-5\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" }, + { 1, " \262\353 \343\322\325\340\325\335\353, \347\342\336 \345\336\342\330\342\325 \322\353\331\342\330? " }, + { 2, " (\260\332\342\330\322\335\320\357)" }, + { 3, " (\270\323\340\353)" }, + { 4, " (\263\333\336\321\320\333\354\335\320\357)" }, + { 5, "(\341\336\321\340\320\335 %s)" }, + { 6, ", \336\350\330\321\332\320 \322\336 \322\340\325\334\357 \337\336\324\332\333\356\347\325\335\330\357 \337\320\337\332\330" }, + { 7, ", \337\320\337\332\320 \335\325 \337\336\324\332\333\356\347\325\335\320" }, + { 8, "... \330\351\343 ..." }, + { 9, "11 \332\263\346" }, + { 10, "22 \332\263\346" }, + { 11, "44 \332\263\346" }, + { 12, "48 \332\263\346" }, + { 13, "8 \332\263\346" }, + { 14, "<\337\336 \343\334\336\333\347\320\335\330\356>" }, + { 15, "\276 \337\340\336\323\340\320\334\334\325 ScummVM" }, + { 16, "\315\334\343\333\357\342\336\340 AdLib" }, + { 17, "\315\334\343\333\357\342\336\340 AdLib:" }, + { 18, "\267\322\343\332\336\322\320\357 \332\320\340\342\320 AdLib \330\341\337\336\333\354\327\343\325\342\341\357 \334\335\336\323\330\334\330 \330\323\340\320\334\330" }, + { 19, "\275\336\322. \330\323\340\320..." }, + { 20, "\300\320\341\342\325\340\330\327\320\342\336\340 \341\336 \341\323\333\320\326\330\322\320\335\330\325\334 (16bpp)" }, + { 21, "\272\336\340\340\325\332\346\330\357 \341\336\336\342\335\336\350\325\335\330\357 \341\342\336\340\336\335" }, + { 22, "\275\320\327\335\320\347\325\335\335\320\357 \332\333\320\322\330\350\320 : %s" }, + { 23, "\275\320\327\335\320\347\325\335\335\320\357 \332\333\320\322\330\350\320 : \335\325\342" }, + { 24, "\260\343\324\330\336" }, + { 25, "\260\322\342\336\341\336\345\340\320\335\325\335\330\325:" }, + { 26, "\264\336\341\342\343\337\335\353\325 \324\322\330\326\332\330:" }, + { 27, "\276 \337~\340~\336\323\340\320\334\334\325..." }, + { 28, "\275\320\327\335\320\347\330\342\354 \332\333\320\322\330\350\330" }, + { 29, "\262\341\361" }, + { 30, "\317\340\332\336\341\342\354:" }, + { 31, "\276\342\334\325\335\320" }, + { 32, "\275\325 \334\336\323\343 \341\336\327\324\320\342\354 \344\320\331\333" }, + { 33, "\270\327\334\325\335\330\342\354 \336\337\346\330\330 \330\323\340\353" }, + { 34, "\270\327\334\325\335\330\342\354 \323\333\336\321\320\333\354\335\353\325 \336\337\346\330\330 ScummVM" }, + { 35, "\276\342\334\325\342\354\342\325, \325\341\333\330 \343 \322\320\341 \337\336\324\332\333\356\347\325\335\336 Roland-\341\336\322\334\325\341\342\330\334\336\325 \327\322\343\332\336\322\336\325 \343\341\342\340\336\331\341\342\322\336 \330 \322\353 \345\336\342\330\342\325 \325\323\336 \330\341\337\336\333\354\327\336\322\320\342\354" }, + { 36, "\262\353\321\340\320\342\354" }, + { 37, "\262\353\321\325\340\330\342\325 \324\325\331\341\342\322\330\325 \324\333\357 \335\320\327\335\320\347\325\335\330\357" }, + { 38, "\276\347\330\341\342\330\342\354 \327\335\320\347\325\335\330\325" }, + { 39, "\267\320\332\340\353\342\354" }, + { 40, "\272\336\340\340\325\332\342\330\340\336\322\320\342\354 \341\336\336\342\335\336\350\325\335\330\325 \341\342\336\340\336\335 \324\333\357 \330\323\340 \341 \340\320\327\340\325\350\325\335\330\325\334 320x200" }, + { 41, "\275\325 \334\336\323\343 \335\320\331\342\330 \324\322\330\326\336\332 \324\333\357 \327\320\337\343\341\332\320 \322\353\321\340\320\335\335\336\331 \330\323\340\353" }, + { 42, "\302\325\332\343\351\330\331 \322\330\324\325\336\340\325\326\330\334:" }, + { 43, "\272\343\340\341\336\340 \322\335\330\327" }, + { 44, "\272\343\340\341\336\340 \322\333\325\322\336" }, + { 45, "\272\343\340\341\336\340 \322\337\340\320\322\336" }, + { 46, "\272\343\340\341\336\340 \322\322\325\340\345" }, + { 47, "\315\334\343\333\357\342\336\340 DOSBox OPL" }, + { 48, "DVD" }, + { 49, "DVD \337\336\324\332\333\356\347\325\335 \343\341\337\325\350\335\336" }, + { 50, "DVD \335\325 \337\336\324\332\333\356\347\325\335" }, + { 51, "\264\320\342\320: " }, + { 52, "\276\342\333\320\324\347\330\332" }, + { 53, "\277\336 \343\334\336\333\347\320\335\330\356" }, + { 54, "\303\324\320\333\330\342\354" }, + { 55, "\267\320\337\340\325\342\330\342\354 \322\353\332\333\356\347\325\335\330\325" }, + { 56, "\261\325\327 \323\340\320\344\330\332\330" }, + { 57, "\275\320\331\324\325\335\336 %d \335\336\322\353\345 \330\323\340 ..." }, + { 58, "\275\320\331\324\325\335\336 %d \335\336\322\353\345 \330\323\340." }, + { 59, "\277\336\332\320\327\320\342\354 " }, + { 60, "\277\336\332\320\327\320\342\354 \332\333\320\322\330\320\342\343\340\343" }, + { 61, "\262\353 \324\325\331\341\342\322\330\342\325\333\354\335\336 \345\336\342\330\342\325 \343\324\320\333\330\342\354 \355\342\336 \341\336\345\340\320\335\325\335\330\325?" }, + { 62, "\262\353 \324\325\331\341\342\322\330\342\325\333\354\335\336 \345\336\342\330\342\325 \343\324\320\333\330\342\354 \343\341\342\320\335\336\322\332\330 \324\333\357 \355\342\336\331 \330\323\340\353?" }, + { 63, "\262\353 \324\325\331\341\342\322\330\342\325\333\354\335\336 \345\336\342\330\342\325 \327\320\337\343\341\342\330\342\354 \324\325\342\325\332\342\336\340 \322\341\325\345 \330\323\340? \315\342\336 \337\336\342\325\335\346\330\320\333\354\335\336 \334\336\326\325\342 \324\336\321\320\322\330\342\354 \321\336\333\354\350\336\325 \332\336\333\330\347\325\341\342\322\336 \330\323\340." }, + { 64, "\262\353 \345\336\342\330\342\325 \327\320\323\340\343\327\330\342\354 \333\330\321\336 \341\336\345\340\320\335\330\342\354 \330\323\340\343?" }, + { 65, "\262\353 \345\336\342\330\342\325 \337\340\336\330\327\322\325\341\342\330 \320\322\342\336\334\320\342\330\347\325\341\332\330\331 \337\336\330\341\332?" }, + { 66, "\262\353 \345\336\342\330\342\325 \322\353\331\342\330?" }, + { 67, "\264\322\336\331\335\336\331 \343\324\320\340" }, + { 68, "\262\335\330\327" }, + { 69, "\262\332\333\356\347\330\342\354 \340\325\326\330\334 Roland GS" }, + { 70, "\264\322\330\326\336\332 \335\325 \337\336\324\324\325\340\326\330\322\320\325\342 \343\340\336\322\325\335\354 \336\342\333\320\324\332\330 '%s'" }, + { 71, "English" }, + { 72, "\276\350\330\321\332\320 \327\320\337\343\341\332\320 \330\323\340\353:" }, + { 73, "\276\350\330\321\332\320 \322\336 \322\340\325\334\357 \337\336\324\332\333\356\347\325\335\330\357 DVD" }, + { 74, "\264\336\337. \337\343\342\354:" }, + { 75, "\315\334\343\333\357\342\336\340 FM Towns" }, + { 76, "\261\353\341\342\340\353\331 \340\325\326\330\334" }, + { 77, "\262\332\333\356\347\325\335\335\353\325 \322 \321\330\333\324 \336\337\346\330\330:" }, + { 78, "\301\322\336\321\336\324\335\353\331 \336\321\327\336\340" }, + { 79, "\277\336\333\335\336\325 \335\320\327\322\320\335\330\325 \330\323\340\353" }, + { 80, "\277\336\333\335\336\355\332\340\320\335\335\353\331 \340\325\326\330\334" }, + { 81, "\303\341\332\336\340\325\335\330\325 GC \337\320\324\320:" }, + { 82, "\307\343\322\341\342\320\330\342\325\333\354\335\336\341\342\354 GC \337\320\324\320:" }, + { 83, "\263\340\344" }, + { 84, "\303\341\342\340\336\331\342\341\322\336 GM:" }, + { 85, "\317\327\353\332 \330\335\342\325\340\344\325\331\341\320:" }, + { 86, "\300\320\341\342\325\340\330\327\320\342\336\340 GUI:" }, + { 87, "\270\323\340\320" }, + { 88, "\275\325\342 \344\320\331\333\336\322 \330\323\340\353" }, + { 89, "Game Id \335\325 \337\336\324\324\325\340\326\330\322\320\325\342\341\357" }, + { 90, "\277\343\342\354 \332 \330\323\340\325: " }, + { 91, "\263\333\336\321\320\333\354\335\336\325 \334\325\335\356" }, + { 92, "\277\325\340\325\331\342\330 \335\320 \324\330\340\325\332\342\336\340\330\356 \343\340\336\322\335\325\334 \322\353\350\325" }, + { 93, "\262\322\325\340\345" }, + { 94, "\263\340\320\344\330\332\320" }, + { 95, "\263\340\320\344\330\347\325\341\332\330\331 \340\325\326\330\334:" }, + { 96, "\305\320\340\324\322\320\340\335\336\325 \334\320\341\350\342\320\321\330\340\336\322\320\335\330\325 (\321\353\341\342\340\336, \335\336 \335\330\327\332\336\323\336 \332\320\347\325\341\342\322\320)" }, + { 97, "Hercules \317\335\342\320\340\335\353\331" }, + { 98, "Hercules \267\325\333\325\335\353\331" }, + { 99, "\301\337\340\357\342\320\342\354 \337\320\335\325\333\354 \330\335\341\342\340\343\334\325\335\342\336\322" }, + { 100, "\262\353\341\336\332\336\325 \332\320\347\325\341\342\322\336 \327\322\343\332\320 (\334\325\324\333\325\335\335\325\325) (\340\325\321\343\342)" }, + { 101, "\261\276\333\354\350\330\325 \327\335\320\347\325\335\330\357 \327\320\324\320\356\342 \333\343\347\350\325\325 \332\320\347\325\341\342\322\336 \327\322\343\332\320, \336\324\335\320\332\336 \336\335\330 \334\336\323\343\342 \335\325 \337\336\324\324\325\340\326\330\322\320\342\354\341\357 \322\320\350\325\331 \327\322\343\332\336\322\336\331 \332\320\340\342\336\331" }, + { 102, "\303\324\325\340\326\330\322\320\331\342\325 \332\333\320\322\330\350\343 Shift \324\333\357 \342\336\323\336, \347\342\336\321\353 \324\336\321\320\322\330\342\354 \335\325\341\332\336\333\354\332\336 \330\323\340" }, + { 103, "\263\336\340\330\327\336\335\342\320\333\354\335\353\331 underscan:" }, + { 104, "\315\334\343\333\357\342\336\340 IBM PCjr" }, + { 105, "ID:" }, + { 106, "\270\335\330\346\330\320\333\330\327\320\346\330\357 \341\325\342\330" }, + { 107, "\275\320\347\320\333\354\335\353\331 \334\320\341\350\342\320\321 \322\325\340\345\335\325\323\336 \355\332\340\320\335\320:" }, + { 108, "\275\320\341\342\340\320\330\322\320\356 \355\334\343\333\357\342\336\340 MT-32" }, + { 109, "\275\320\341\342\340\320\330\322\320\356 \341\325\342\354" }, + { 110, "\262\322\336\324" }, + { 111, "\275\325\322\325\340\335\353\331 \337\343\342\354" }, + { 112, "\275\320\327\335\320\347\325\335\330\325 \332\333\320\322\330\350" }, + { 113, "\272\333\320\322\330\320\342\343\340\320" }, + { 114, "\302\320\321\333\330\346\320 \332\333\320\322\330\350:" }, + { 115, "\272\333\320\322\330\350\330" }, + { 116, "\317\327\353\332 \323\340\320\344\330\347\325\341\332\336\323\336 \330\335\342\325\340\344\325\331\341\320 ScummVM" }, + { 117, "\317\327\353\332 \330\323\340\353. \270\327\334\325\335\325\335\330\325 \355\342\336\323\336 \337\320\340\320\334\325\342\340\320 \335\325 \337\340\325\322\340\320\342\330\342 \330\323\340\343 \335\320 \320\335\323\333\330\331\341\332\336\334 \322 \340\343\341\341\332\343\356" }, + { 118, "\317\327\353\332:" }, + { 119, "\262\333\325\322\336" }, + { 120, "\273\325\322\353\331 \351\325\333\347\336\332" }, + { 121, "\267\320\323\340\343\327\330\342\354" }, + { 122, "\267\320\323\340\343\327\330\342\354 \330\323\340\343:" }, + { 123, "\267\320\323\340\343\327\330\342\354 \341\336\345\340\335\325\335\330\325 \324\333\357 \322\353\321\340\320\335\335\336\331 \330\323\340\353" }, + { 124, "\315\334\343\333\357\342\336\340 MAME OPL:" }, + { 125, "MIDI" }, + { 126, "\303\341\330\333\325\335\330\325 MIDI:" }, + { 127, "\303\341\342\340\336\331\341\342\322\336 MT32:" }, + { 128, "\315\334\343\333\357\342\336\340 MT-32" }, + { 129, "\274\320\341\350\342\320\321 \323\333\320\322\335\336\323\336 \355\332\340\320\335\320:" }, + { 130, "\275\320\327\335\320\347\330\342\354" }, + { 131, "\264\336\321. \334\335\336\323\336..." }, + { 132, "\274\325\335\356" }, + { 133, "\300\320\327\335\336\325" }, + { 134, "\301\334\325\350\320\335\335\353\331 \340\325\326\330\334 AdLib/MIDI" }, + { 135, "\277\336\324\332\333\356\347\330\342\354 DVD" }, + { 136, "\277\336\324\332\333\356\347\330\342\354 SMB" }, + { 137, "\272\333\330\332 \334\353\350\354\356" }, + { 138, "\274\343\333\354\342\330\344\343\335\332\346\330\357" }, + { 139, "\303\341\342\340\336\331\342\341\322\336 GM:" }, + { 140, "\263\340\336\334\332\336\341\342\354 \334\343\327\353\332\330:" }, + { 141, "\262\353\332\333\356\347\330\342\354 \322\341\361" }, + { 142, "\275\320\327\322\320\335\330\325:" }, + { 143, "\301\325\342\354 \322\353\332\333\356\347\325\335\320" }, + { 144, "\301\325\342\354 \335\325 \335\320\341\342\340\336\325\335\320 (%d)" }, + { 145, "\301\325\342\354 \340\320\321\336\342\320\325\342" }, + { 146, "\301\325\342\354 \340\320\321\336\342\320\325\342, \337\320\337\332\320 \337\336\324\332\333\356\347\325\335\320" }, + { 147, "\275\330\332\336\323\324\320" }, + { 148, "\275\325\342" }, + { 149, "\264\320\342\320 \335\325 \327\320\337\330\341\320\335\320" }, + { 150, "\261\325\327 \334\343\327\353\332\330" }, + { 151, "\262\340\325\334\357 \330\323\340\353 \335\325 \327\320\337\330\341\320\335\336" }, + { 152, "\262\340\325\334\357 \335\325 \327\320\337\330\341\320\335\336" }, + { 153, "\275\325 \327\320\324\320\335" }, + { 154, "\261\325\327 \343\322\325\333\330\347\325\335\330\357" }, + { 155, "OK" }, + { 156, "\262\353\345\336\324\335\320\357 \347\320\341\342\336\342\320:" }, + { 157, "\277\325\340\325\332\340\353\342\354 \323\333\336\321\320\333\354\335\353\325 \343\341\342\320\335\336\322\332\330 MIDI" }, + { 158, "\277\325\340\325\332\340\353\342\354 \323\333\336\321\320\333\354\335\353\325 \343\341\342\320\335\336\322\332\330 \320\343\324\330\336" }, + { 159, "\277\325\340\325\332\340\353\342\354 \323\333\336\321\320\333\354\335\353\325 \343\341\342\320\335\336\322\332\330 \323\340\320\344\330\332\330" }, + { 160, "\277\325\340\325\332\340\353\342\354 \323\333\336\321\320\333\354\335\353\325 \343\341\342\320\335\336\322\332\330 \323\340\336\334\332\336\341\342\330" }, + { 161, "\315\334\343\333\357\342\336\340 PC \341\337\330\332\325\340\320" }, + { 162, "\277\320\340\336\333\354:" }, + { 163, "\277\343\342\354 \335\325 \357\322\333\357\325\342\341\357 \324\330\340\325\332\342\336\340\330\325\331" }, + { 164, "\277\343\342\354 \335\325 \357\322\333\357\325\342\341\357 \344\320\331\333\336\334" }, + { 165, "\277\343\342\354 \335\325 \335\320\331\324\325\335" }, + { 166, "\277\343\342\330" }, + { 167, "\277\320\343\327\320" }, + { 168, "\262\353\321\325\340\330\342\325 \330\323\340\343:" }, + { 169, "\277\333\320\342\344\336\340\334\320, \324\333\357 \332\336\342\336\340\336\331 \330\323\340\320 \321\353\333\320 \330\327\335\320\347\320\333\354\335\336 \340\320\327\340\320\321\336\342\320\335\320" }, + { 170, "\277\333\320\342\344\336\340\334\320:" }, + { 171, "\262\340\325\334\357 \330\323\340\353: " }, + { 172, "\277\336\326\320\333\343\331\341\342\320, \322\353\321\325\340\330\342\325 \324\325\331\341\342\322\330\325" }, + { 173, "\277\343\342\354 \332 \337\333\320\323\330\335\320\334:" }, + { 174, "\277\340\325\324\337\336\347\330\342\320\325\334\336\325 \343\341\342\340\336\331\341\342\322\336:" }, + { 175, "\275\320\326\334\330\342\325 \332\333\320\322\330\350\343 \324\333\357 \335\320\327\335\320\347\325\335\330\357" }, + { 176, "\262\353\345\336\324" }, + { 177, "\262\353\345\336\324 \330\327 ScummVM" }, + { 178, "\275\325\324\336\341\342\320\342\336\347\335\336 \337\340\320\322 \324\333\357 \347\342\325\335\330\357" }, + { 179, "\276\350\330\321\332\320 \347\342\325\335\330\357" }, + { 180, "\277\325\340\325\335\320\327\335\320\347\330\342\354 \332\333\320\322\330\350\330" }, + { 181, "\303\324\320\333\330\342\354 \330\323\340\343 \330\327 \341\337\330\341\332\320. \275\325 \343\324\320\333\357\325\342 \330\323\340\343 \341 \326\325\341\342\332\336\323\336 \324\330\341\332\320" }, + { 182, "\300\325\326\330\334 \340\320\341\342\340\330\340\336\322\320\335\330\357:" }, + { 183, "\262\337\340\320\322\336" }, + { 184, "\277\340\320\322\353\331 \351\325\333\347\336\332" }, + { 185, "\277\340\320\322\353\331 \351\325\333\347\336\332" }, + { 186, "\277\336\322\325\340\335\343\342\354" }, + { 187, "\263\340\336\334\332\336\341\342\354 \355\344\344\325\332\342\336\322:" }, + { 188, "SMB" }, + { 189, "\267\320\337\330\341\320\342\354" }, + { 190, "\277\343\342\354 \341\336\345\340.: " }, + { 191, "\277\343\342\354 \324\333\357 \341\336\345\340\320\335\325\335\330\331: " }, + { 192, "\301\336\345\340\320\335\330\342\354 \330\323\340\343: " }, + { 193, "\277\336\330\341\332 \327\320\332\336\335\347\325\335!" }, + { 194, "\277\340\336\341\334\336\342\340\325\335\336 %d \324\330\340\325\332\342\336\340\330\331 ..." }, + { 195, "\263\333\320\322\335\336\325 \334\325\335\356 ScummVM" }, + { 196, "ScummVM \335\325 \341\334\336\323 \335\320\331\342\330 \324\322\330\326\336\332 \324\333\357 \327\320\337\343\341\332\320 \322\353\321\340\320\335\335\336\331 \330\323\340\353!" }, + { 197, "ScummVM \335\325 \334\336\326\325\342 \335\320\331\342\330 \330\323\340\343 \322 \343\332\320\327\320\335\335\336\331 \324\330\340\325\332\342\336\340\330\330!" }, + { 198, "ScummVM \335\325 \334\336\326\325\342 \336\342\332\340\353\342\354 \343\332\320\327\320\335\335\343\356 \324\330\340\325\332\342\336\340\330\356!" }, + { 199, "\277\336\330\341\332 \322 \341\337\330\341\332\325 \330\323\340" }, + { 200, "\277\336\330\341\332:" }, + { 201, "\262\353\321\325\340\330\342\325 SoundFont" }, + { 202, "\262\353\321\325\340\330\342\325 \342\325\334\343" }, + { 203, "\262\353\321\325\340\330\342\325 \324\336\337\336\333\335\330\342\325\333\354\335\343\356 \324\330\340\325\332\342\336\340\330\356 \330\323\340\353" }, + { 204, "\262\353\321\325\340\330\342\325 \324\325\331\341\342\322\330\325 \330 \332\333\330\332\335\330\342\325 '\275\320\327\335\320\347\330\342\354'" }, + { 205, "\262\353\321\325\340\330\342\325 \324\330\340\325\332\342\336\340\330\356 \324\333\357 \342\325\334 GUI" }, + { 206, "\262\353\321\325\340\330\342\325 \324\330\340\325\332\342\336\340\330\356 \341 \324\336\337\336\333\335\330\342\325\333\354\335\353\334\330 \344\320\331\333\320\334\330" }, + { 207, "\262\353\321\325\340\330\342\325 \324\330\340\325\332\342\336\340\330\356 \341 \337\333\320\323\330\335\320\334\330" }, + { 208, "\262\353\321\325\340\330\342\325 \324\330\340\325\332\342\336\340\330\356 \324\333\357 \341\336\345\340\320\335\325\335\330\331" }, + { 209, "\262\353\321\325\340\330\342\325 \324\330\340\325\332\342\336\340\330\356 \324\333\357 \341\336\345\340\320\335\325\335\330\331" }, + { 210, "\262\353\321\325\340\330\342\325 \324\330\340\325\332\342\336\340\330\356 \341 \344\320\331\333\320\334\330 \330\323\340\353" }, + { 211, "\307\343\322\341\342\322\330\342\325\333\354\335\336\341\342\354" }, + { 212, "\301\325\340\322\325\340:" }, + { 213, "\301\325\342\325\322\320\357 \337\320\337\332\320:" }, + { 214, "\272\336\340\336\342\332\330\331 \330\324\325\335\342\330\344\330\332\320\342\336\340, \330\341\337\336\333\354\327\343\325\334\353\331 \324\333\357 \330\334\325\335 \341\336\345\340\320\335\325\335\330\331 \330\323\340 \330 \324\333\357 \327\320\337\343\341\332\320 \330\327 \332\336\334\320\335\324\335\336\331 \341\342\340\336\332\330" }, + { 215, "\277\336\332\320\327\320\342\354 \332\333\320\322\330\320\342\343\340\343" }, + { 216, "\277\336\332\320\327\353\322\320\342\354 \332\343\340\341\336\340 \334\353\350\330" }, + { 217, "\277\336\332\320\327\353\322\320\342\354 \341\343\321\342\330\342\340\353 \330 \322\336\341\337\340\336\330\327\322\336\324\330\342\354 \340\325\347\354" }, + { 218, "\277\336\332\320\327\320\342\354/\303\321\340\320\342\354 \332\343\340\341\336\340" }, + { 219, "\277\340\336\337\343\341\342\330\342\354" }, + { 220, "\277\340\336\337\343\341\342\330\342\354 \341\342\340\336\332\343" }, + { 221, "\277\340\336\337\343\341\342\330\342\354 \342\325\332\341\342" }, + { 222, "\277\340\330\332\340\325\337\330\342\354 \332 \323\340\320\335\330\346\320\334" }, + { 223, "\277\340\336\323\340\320\334\334\335\336\325 \334\320\341\350\342\320\321\330\340\336\322\320\335\330\325 (\345\336\340\336\350\325\325 \332\320\347\325\341\342\322\336, \335\336 \334\325\324\333\325\335\335\325\325)" }, + { 224, "\267\322\343\332 \322\332\333/\322\353\332\333" }, + { 225, "SoundFont\353 \337\336\324\324\325\340\324\326\330\322\320\356\342\341\357 \335\325\332\336\342\336\340\353\334\330 \327\322\343\332\336\322\353\334\330 \332\320\340\342\320\334\330, Fluidsynth \330 Timidity" }, + { 226, "SoundFont:" }, + { 227, "\276\327\322" }, + { 228, "\301\337\325\346\330\320\333\354\335\353\325 \340\325\326\330\334\353 \340\325\335\324\325\340\330\335\323\320, \337\336\324\324\325\340\326\330\322\320\325\334\353\325 \335\325\332\336\342\336\340\353\334\330 \330\323\340\320\334\330" }, + { 229, "\263\340\336\334\332\336\341\342\354 \341\337\325\346\330\320\333\354\335\353\345 \327\322\343\332\336\322\353\345 \355\344\344\325\332\342\336\322" }, + { 230, "\303\332\320\327\353\322\320\325\342 \322\353\345\336\324\335\336\325 \327\322\343\332\336\322\336\325 \343\341\342\340\336\331\341\342\322\336 \324\333\357 MIDI" }, + { 231, "\303\332\320\327\353\322\320\325\342 \327\322\343\332\336\322\336\325 \343\341\342\340\336\331\341\342\322\336 \337\336 \343\334\336\333\347\320\335\330\357 \324\333\357 \322\353\322\336\324\320 \335\320 Roland MT-32/LAPC1/CM32l/CM64" }, + { 232, "\303\332\320\327\353\322\320\325\342 \322\353\345\336\324\335\336\325 \327\322\343\332\336\322\336\325 \343\341\342\340\336\331\341\342\322\336 \330\333\330 \355\334\343\333\357\342\336\340 \327\322\343\332\336\322\336\331 \332\320\340\342\353" }, + { 233, "\303\332\320\327\353\322\320\325\342 \337\343\342\354 \332 \324\336\337\336\333\335\330\342\325\333\354\335\353\334 \344\320\331\333\320\334 \324\320\335\335\353\345, \330\341\337\336\333\354\327\343\325\334\353\345 \322\341\325\334\330 \330\323\340\320\334\330, \333\330\321\336 ScummVM" }, + { 234, "\303\332\320\327\353\322\320\325\342 \337\343\342\354 \332 \324\336\337\336\333\335\330\342\325\333\354\335\353\334 \344\320\331\333\320\334 \324\320\335\335\353\345 \324\333\357 \330\323\340\353" }, + { 235, "\303\332\320\327\353\322\320\325\342 \322\353\345\336\324\335\336\325 \327\322\343\332\336\322\336\325 \343\341\342\340\336\331\341\342\322\336 \330\333\330 \355\334\343\333\357\342\336\340 \327\322\343\332\336\322\336\331 \332\320\340\342\353" }, + { 236, "\303\332\320\327\353\322\320\325\342 \337\343\342\354 \332 \341\336\345\340\320\335\325\335\330\357\334 \330\323\340\353" }, + { 237, "\276\327\322\343\347\332\320" }, + { 238, "\263\340\336\334\332\336\341\342\354 \336\327\322\343\347\332\330:" }, + { 239, "\301\342\320\335\324\320\340\342\335\353\331 \340\320\341\342\325\340\330\327\320\342\336\340 (16bpp)" }, + { 240, "\267\320\337\343\341\342\330\342\354 \322\353\321\340\320\335\335\343\356 \330\323\340\343" }, + { 241, "\301\336\341\342\336\357\335\330\325:" }, + { 242, "\301\343\321" }, + { 243, "\301\332\336\340\336\341\342\354 \341\343\321\342\330\342\340\336\322:" }, + { 244, "\301\343\321\342\330\342\340\353" }, + { 245, "\301\334\325\335\330\342\354 \323\325\340\336\357" }, + { 246, "\302\320\337 \324\333\357 \333\325\322\336\323\336 \351\325\333\347\332\320, \324\322\336\331\335\336\331 \342\320\337 \324\333\357 \337\340\320\322\336\323\336 \351\325\333\347\332\320" }, + { 247, "\302\325\332\341\342 \330 \336\327\322\343\347\332\320:" }, + { 248, "\275\325 \334\336\323\343 \337\330\341\320\342\354 \322 \322\353\321\340\320\335\335\343\356 \324\330\340\325\332\342\336\340\330\356. \277\336\326\320\333\343\331\341\342\320, \343\332\320\326\330\342\325 \324\340\343\323\343\356." }, + { 249, "\277\343\342\354 \332 \342\325\334\320\334:" }, + { 250, "\302\325\334\320:" }, + { 251, "\315\342\336\342 ID \330\323\340\353 \343\326\325 \330\341\337\336\333\354\327\343\325\342\341\357. \277\336\326\320\333\343\331\341\342\320, \322\353\321\325\340\330\342\325 \324\340\343\323\336\331." }, + { 252, "\315\342\320 \330\323\340\320 \335\325 \337\336\324\324\325\340\326\330\322\320\325\342 \327\320\323\340\343\327\332\343 \341\336\345\340\320\335\325\335\330\331 \347\325\340\325\327 \323\333\320\322\335\336\325 \334\325\335\356." }, + { 253, "\262\340\325\334\357: " }, + { 254, "\262\340\325\334\357 \337\336\324\332\333\356\347\325\335\330\357 \332 \341\325\342\330 \330\341\342\325\332\333\336" }, + { 255, "\301\334\325\351\325\335\330\325 \332\320\341\320\335\330\331 \337\336 \336\341\330 X" }, + { 256, "\301\334\325\351\325\335\330\325 \332\320\341\320\335\330\331 \337\336 \336\341\330 Y" }, + { 257, "\300\325\326\330\334 \342\320\347\337\320\324\320 \322\353\332\333\356\347\325\335." }, + { 258, "\300\325\326\330\334 \342\320\347\337\320\324\320 \322\332\333\356\347\325\335." }, + { 259, "\275\320\341\342\336\357\351\330\331 Roland MT-32 (\327\320\337\340\325\342\330\342\354 \355\334\343\333\357\346\330\356 GM)" }, + { 260, "\262\353\332\333\356\347\320\325\342 \334\320\337\337\330\335\323 General MIDI \324\333\357 \330\323\340 \341 \327\322\343\332\336\322\336\331 \324\336\340\336\326\332\336\331 \324\333\357 Roland MT-32" }, + { 261, "\275\325\330\327\322\325\341\342\335\336" }, + { 262, "\275\325\330\327\322\325\341\342\335\320\357 \336\350\330\321\332\320" }, + { 263, "\276\342\332\333\356\347\330\342\354 DVD" }, + { 264, "\276\342\332\333\356\347\342\354 SMB" }, + { 265, "\261\325\327 \334\320\341\350\342\320\321\330\340\336\322\320\335\330\357 (\335\343\326\335\336 \321\343\324\325\342 \337\340\336\332\340\343\347\330\322\320\342\354 \322\333\325\322\336 \330 \322\337\340\320\322\336)" }, + { 266, "\275\325\337\336\324\324\325\340\326\330\322\320\325\334\353\331 \340\325\326\330\334 \346\322\325\342\320" }, + { 267, "\301\336\345\340\320\335\325\335\330\325 \321\325\327 \330\334\325\335\330" }, + { 268, "\262\322\325\340\345" }, + { 269, "\270\341\337\336\333\354\327\336\322\320\342\354 \330 MIDI \330 AdLib \324\333\357 \323\325\335\325\340\320\346\330\330 \327\322\343\332\320" }, + { 270, "\270\341\337\336\333\354\327\336\322\320\342\354 \343\337\340\320\322\333\325\335\330\325 \332\343\340\341\336\340\336\334 \332\320\332 \335\320 \342\340\325\332\337\320\324\325 \333\325\337\342\336\337\336\322" }, + { 271, "\277\336\333\354\327\336\322\320\342\325\333\354:" }, + { 272, "\270\341\337\336\333\354\327\343\356 \324\340\320\331\322\325\340 SDL " }, + { 273, "\262\325\340\342\330\332\320\333\354\335\353\331 underscan:" }, + { 274, "\262\330\324\325\336" }, + { 275, "\262\330\340\342\343\320\333\354\335\320\357 \332\333\320\322\330\320\342\343\340\320" }, + { 276, "\263\340\336\334\332\336\341\342\354" }, + { 277, "Windows MIDI" }, + { 278, "\275\325\324\336\341\342\320\342\336\347\335\336 \337\340\320\322 \324\333\357 \327\320\337\330\341\330" }, + { 279, "\276\350\330\321\332\320 \327\320\337\330\341\330 \324\320\335\335\353\345" }, + { 280, "\264\320" }, + { 281, "\262\353 \324\336\333\326\335\353 \337\325\340\325\327\320\337\343\341\342\330\342\354 ScummVM \347\342\336\321\353 \337\340\330\334\325\335\330\342\354 \330\327\334\325\335\325\335\330\357." }, + { 282, "\267\336\335\320" }, + { 283, "\303\334\325\335\354\350. \334\320\341\350\342\320\321" }, + { 284, "\303\322\325\333. \334\320\341\350\342\320\321" }, + { 285, "\332\320\326\324\353\325 10 \334\330\335\343\342" }, + { 286, "\332\320\326\324\353\325 15 \334\330\335\343\342" }, + { 287, "\332\320\326\324\353\325 30 \334\330\335\343\342" }, + { 288, "\332\320\326\324\353\325 5 \334\330\335\343\342" }, + { 289, "\276 \337\340\336~\323~\340\320\334\334\325" }, + { 290, "~\264~\336\321. \330\323\340\343..." }, + { 291, "\276~\342~\334\325\335\320" }, + { 292, "~\267~\320\332\340\353\342\354" }, + { 293, "\270\327~\334~. \330\323\340\343..." }, + { 294, "~\277~\336\334\336\351\354" }, + { 295, "\303\337\340\320\322\333\325\335\330\325 \321\336\357\334\330 \322 Indy" }, + { 296, "~\272~\333\320\322\330\350\330" }, + { 297, "\273\325\322\336\340\343\332\330\331 \340\325\326\330\334" }, + { 298, "~\267~\320\323\340\343\327\330\342\354" }, + { 299, "~\267~\320\323\340...." }, + { 300, "~\301~\333\325\324" }, + { 301, "~O~K" }, + { 302, "~\276~\337\346\330\330" }, + { 303, "~\276~\337\346\330\330..." }, + { 304, "~\277~\340\325\324" }, + { 305, "~\262~\353\345\336\324" }, + { 306, "~\303~\324\320\333\330\342\354 \330\323\340\343" }, + { 307, "\277\340\336\324\336\333~\326~\330\342\354" }, + { 308, "~\262~\325\340\335\343\342\354\341\357 \322 \323\333\320\322\335\336\325 \334\325\335\356" }, + { 309, "~\267~\320\337\330\341\320\342\354" }, + { 310, "\277~\343~\341\332" }, + { 311, "\277\325\340\325\345\336\324\353 \320\332\342\330\322\330\340\336\322\320\335\353" }, + { 312, "\315\344\344\325\332\342\353 \322\336\324\353 \322\332\333\356\347\325\335\353" }, + { 313, "\300\325\326\330\334 \321\353\341\342\340\336\323\336 \337\325\340\325\345\336\324\320 \320\332\342\330\322\330\340\336\322\320\335" }, + { -1, NULL } +}; + +static const PoMessageEntry _translation_fr_FR[] = { + { 0, "Project-Id-Version: ScummVM 1.2.0svn\nReport-Msgid-Bugs-To: scummvm-devel@lists.sf.net\nPOT-Creation-Date: 2010-07-12 17:44+0200\nPO-Revision-Date: 2010-07-09 18:17+0100\nLast-Translator: Thierry Crozat <criezy@scummvm.org>\nLanguage-Team: French <scummvm-devel@lists.sf.net>\nLanguage: Francais\nMIME-Version: 1.0\nContent-Type: text/plain; charset=iso-8859-1\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=n>1;\n" }, + { 1, "Voulez-vous vraiment quitter?" }, + { 2, "(Actif)" }, + { 3, "(Jeu)" }, + { 4, "(Global)" }, + { 5, "(compil\351 sur %s)" }, + { 6, ", \351chec du montage du disque partag\351" }, + { 7, ", disque partag\351 non mont\351" }, + { 8, "... en cours ..." }, + { 9, "11 kHz" }, + { 10, "22 kHz" }, + { 11, "44 kHz" }, + { 12, "48 kHz" }, + { 13, "8 kHz" }, + { 14, "<defaut>" }, + { 15, "\300 propos de ScummVM" }, + { 16, "\311mulateur AdLib" }, + { 17, "\311mulateur AdLib:" }, + { 18, "AdLib est utilis\351 pour la musique dans de nombreux jeux" }, + { 19, "Ajouter..." }, + { 20, "Anti-cr\351nel\351 (16 bpp)" }, + { 21, "Correction du rapport d'aspect" }, + { 22, "Touche associ\351e: %s" }, + { 23, "Touche associ\351e: aucune" }, + { 24, "Audio" }, + { 25, "Sauvegarde auto:" }, + { 26, "Moteurs disponibles:" }, + { 27, "\300 ~P~ropos..." }, + { 28, "Affecter les touches" }, + { 29, "Les deux" }, + { 30, "Luminosit\351:" }, + { 31, "Annuler" }, + { 32, "Impossible de cr\351er le fichier" }, + { 33, "Change les options du jeu" }, + { 34, "Change les options globales de ScummVM" }, + { 35, "V\351rifie si vous voulez utiliser un p\351riph\351rique audio compatible Roland connect\351 \340 l'ordinateur" }, + { 36, "Choisir" }, + { 37, "S\351lectionnez une action \340 affecter" }, + { 38, "Effacer la valeur" }, + { 39, "Fermer" }, + { 40, "Corrige le rapport d'aspect pour les jeu 320x200" }, + { 41, "Impossible de trouver un moteur pour ex\351cuter le jeu s\351lectionn\351" }, + { 42, "Mode vid\351o actuel" }, + { 43, "Bas" }, + { 44, "Gauche" }, + { 45, "Droit" }, + { 46, "Haut" }, + { 47, "\311mulateur DOSBox OPL" }, + { 48, "DVD" }, + { 49, "DVD mont\351 avec succ\350s" }, + { 50, "DVD non mont\351" }, + { 51, "Date:" }, + { 52, "Debugger" }, + { 53, "D\351faut" }, + { 54, "Supprimer" }, + { 55, "D\351sactiv\351 l'extinction" }, + { 56, "GFX d\351sactiv\351" }, + { 57, "%d nouveaux jeux trouv\351s ..." }, + { 58, "%d nouveaux jeux trouv\351s." }, + { 59, "Affichage" }, + { 60, "Afficher le clavier" }, + { 61, "Voulez-vous vraiment supprimer cette sauvegarde?" }, + { 62, "Voulez-vous vraiment supprimer ce jeu?" }, + { 63, "Voulez-vous vraiment lancer la d\351tection automatique des jeux? Cela peut potentiellement ajouter un grand nombre de jeux." }, + { 64, "Voulez-vous charger ou sauver le jeu?" }, + { 65, "Voulez-vous ex\351cuter une recherche automatique?" }, + { 66, "Voulez-vous quitter?" }, + { 67, "Coup double" }, + { 68, "Bas" }, + { 69, "Activer le mode Roland GS" }, + { 70, "Le niveau de debug '%s' n'est pas support\351 par ce moteur de jeu" }, + { 71, "Anglais" }, + { 72, "Erreur lors de l'\351x\351cution du jeu:" }, + { 73, "\311chec du montage du DVD" }, + { 74, "Extra:" }, + { 75, "\311mulateur FM Towns" }, + { 76, "Mode rapide" }, + { 77, "Options incluses:" }, + { 78, "Regarder autour" }, + { 79, "Nom complet du jeu" }, + { 80, "Plein \351cran" }, + { 81, "Acceleration du pad GC:" }, + { 82, "Sensibilit\351 du pad GC:" }, + { 83, "GFX" }, + { 84, "Sortie GM:" }, + { 85, "Langue:" }, + { 86, "Interface:" }, + { 87, "Jeu" }, + { 88, "Fichier de don\351es introuvable" }, + { 89, "ID de jeu non support\351" }, + { 90, "Chemin du Jeu:" }, + { 91, "Menu global" }, + { 92, "Remonte d'un niveau dans la hi\351rarchie de r\351pertoire" }, + { 93, "Remonter" }, + { 94, "Graphique" }, + { 95, "Mode graphique:" }, + { 96, "Mise \340 l'echelle mat\351rielle (rapide mais qualit\351 faible)" }, + { 97, "Hercules Ambre" }, + { 98, "Hercules Vert" }, + { 99, "Cach\351 la barre d'outils" }, + { 100, "Audio haute qualit\351 (plus lent) (red\351marrer)" }, + { 101, "Une valeur plus \351lev\351e donne une meilleure qualit\351 audio mais peut ne pas \352tre support\351 par votre carte son" }, + { 102, "Ajoute un jeu \340 la Liste. Maintenez Shift enfonc\351e pour un Ajout Massif" }, + { 103, "Underscan horizontal:" }, + { 104, "\311mulateur IBM PCjr" }, + { 105, "ID:" }, + { 106, "Initialiser le r\351seau" }, + { 107, "\311chelle initiale de l'\351cran du haut" }, + { 108, "Initialisation de l'\311mulateur MT-32" }, + { 109, "Initialisation du r\351seau" }, + { 110, "Entr\351e" }, + { 111, "Chemin Invalide" }, + { 112, "Affectation des touches" }, + { 113, "Clavier" }, + { 114, "Affectation des touches:" }, + { 115, "Touches" }, + { 116, "Langue de l'interface graphique de ScummVM" }, + { 117, "Langue du jeu. Cela ne traduira pas en anglais par magie votre version espagnole du jeu." }, + { 118, "Langue:" }, + { 119, "Gauche" }, + { 120, "Clic Gauche" }, + { 121, "Charger" }, + { 122, "Charger le jeu:" }, + { 123, "Charge une sauvegarde pour le jeu s\351lectionn\351" }, + { 124, "\311mulateur MAME OPL" }, + { 125, "MIDI" }, + { 126, "Gain MIDI:" }, + { 127, "Sortie MT-32:" }, + { 128, "\311mulateur MT-32" }, + { 129, "\311chelle de l'\351cran principal" }, + { 130, "Affecter" }, + { 131, "Ajout Massif..." }, + { 132, "Menu" }, + { 133, "Divers" }, + { 134, "Mode mixe AdLib/MIDI" }, + { 135, "Monter le DVD" }, + { 136, "Monter SMB" }, + { 137, "Clic de souris" }, + { 138, "Fonction Multiple" }, + { 139, "Sortie Audio:" }, + { 140, "Volume Musique:" }, + { 141, "Silence" }, + { 142, "Nom:" }, + { 143, "R\351seau d\351connect\351" }, + { 144, "R\351seau non initialis\351 (%d)" }, + { 145, "R\351seau connect\351" }, + { 146, "R\351seau connect\351, disque partag\351 mont\351" }, + { 147, "Jamais" }, + { 148, "Non" }, + { 149, "Date non sauv\351e" }, + { 150, "Pas de musique" }, + { 151, "Dur\351e de jeu non sauv\351e" }, + { 152, "Heure non sauv\351e" }, + { 153, "Aucun" }, + { 154, "Normal (\351chelle d'origine)" }, + { 155, "OK" }, + { 156, "Fr\351quence:" }, + { 157, "Utiliser des r\351glages MIDI sp\351cifiques \340 ce jeux" }, + { 158, "Utiliser des r\351glages audio sp\351cifiques \340 ce jeux" }, + { 159, "Utiliser des r\351glages graphiques sp\351cifiques \340 ce jeux" }, + { 160, "Utiliser des r\351glages de volume sonore sp\351cifiques \340 ce jeux" }, + { 161, "\311mulateur Haut Parleur PC" }, + { 162, "Mot de passe:" }, + { 163, "Chemin n'est pas un r\351pertoire" }, + { 164, "Chemin n'est pas un fichier" }, + { 165, "Chemin inexistant" }, + { 166, "Chemins" }, + { 167, "Mettre en pause" }, + { 168, "Choisissez le jeu:" }, + { 169, "Plateforme pour laquelle votre jeu a \351t\351 con\347u" }, + { 170, "Plateforme:" }, + { 171, "Dur\351e de jeu:" }, + { 172, "Selectionnez une action" }, + { 173, "Plugins:" }, + { 174, "Sortie Pr\351f\351r\351:" }, + { 175, "Appuyez sur la touche \340 associer" }, + { 176, "Quitter" }, + { 177, "Quitter ScummVM" }, + { 178, "V\351roulli\351 en lecture" }, + { 179, "Echec de la lecture" }, + { 180, "Changer l'affectation des touches" }, + { 181, "Supprime le jeu de la liste. Les fichiers sont conserv\351s" }, + { 182, "Mode de rendu:" }, + { 183, "Droite" }, + { 184, "Clic Droit" }, + { 185, "Clic droit" }, + { 186, "Pivoter" }, + { 187, "Volume Bruitage:" }, + { 188, "SMB" }, + { 189, "Sauver" }, + { 190, "Sauvegardes:" }, + { 191, "Sauvegardes:" }, + { 192, "Sauvegarde:" }, + { 193, "Examen termin\351!" }, + { 194, "%d r\351pertoires examin\351s ..." }, + { 195, "Menu Principal ScummVM" }, + { 196, "ScummVM n'a pas pu trouv\351 de moteur pour lancer le jeu s\351lectionn\351." }, + { 197, "ScummVM n'a pas trouv\351 de jeux dans le r\351pertoire s\351lectionn\351." }, + { 198, "ScummVM n'a pas pu ouvrir le r\351pertoire s\351lectionn\351." }, + { 199, "Recherche dans la liste de jeux" }, + { 200, "Filtre:" }, + { 201, "Choisir une banque de sons" }, + { 202, "S\351lectionnez un Th\350me" }, + { 203, "S\351lectionner un r\351pertoire suppl\351mentaire" }, + { 204, "Selectionez une action et cliquez 'Affecter'" }, + { 205, "S\351lectionner le r\351pertoire des th\350mes d'interface" }, + { 206, "S\351lectionner le r\351pertoire pour les fichiers supl\351mentaires" }, + { 207, "S\351lectionner le r\351pertoire des plugins" }, + { 208, "S\351lectionner le r\351pertoire pour les sauvegardes" }, + { 209, "S\351lectionner le r\351pertoire pour les sauvegardes" }, + { 210, "S\351lectionner le r\351pertoire contenant les donn\351es du jeu" }, + { 211, "Sensibilit\351" }, + { 212, "Serveur:" }, + { 213, "Disque partag\351:" }, + { 214, "ID compact du jeu utilis\351 pour identifier les sauvegardes et d\351marrer le jeu depuis la ligne de commande" }, + { 215, "Afficher le clavier" }, + { 216, "Afficher le curseur de la souris" }, + { 217, "Affiche les sous-titres et joue les dialogues audio" }, + { 218, "Afficher/Cacher le curseur" }, + { 219, "Passer" }, + { 220, "Passer la phrase" }, + { 221, "Sauter le texte" }, + { 222, "Aligner sur les bords" }, + { 223, "Mise \340 l'\351chelle logicielle (bonne qualit\351 mais plus lent)" }, + { 224, "Audio marche/arr\352t" }, + { 225, "La banque de sons est utilis\351e par certaines cartes audio, Fluidsynth et Timidity" }, + { 226, "Banque de sons:" }, + { 227, "Audio" }, + { 228, "Mode sp\351cial de tramage support\351 par certains jeux" }, + { 229, "Volume des effets sp\351ciaux sonores" }, + { 230, "Sp\351cifie le p\351riph\351rique audio par d\351faut pour la sortie General MIDI" }, + { 231, "Sp\351cifie le p\351riph\351rique audio par d\351faut pour la sortie Roland MT-32/LAPC1/CM32l/CM64" }, + { 232, "Sp\351cifie le p\351riph\351rique de sortie audio ou l'\351mulateur de carte audio" }, + { 233, "Sp\351cifie un chemin vers des donn\351es suppl\351mentaires utilis\351es par tous les jeux ou ScummVM" }, + { 234, "D\351finie un chemin vers des donn\351es supl\351mentaires utilis\351es par le jeu" }, + { 235, "Sp\351cifie le p\351riph\351rique de sortie audio ou l'\351mulateur de carte audio pr\351f\351r\351" }, + { 236, "D\351finie l'emplacement o\371 les fichiers de sauvegarde sont cr\351\351s" }, + { 237, "Audio" }, + { 238, "Volume Dialogues:" }, + { 239, "Standard (16bpp)" }, + { 240, "D\351marre le jeu s\351lectionn\351" }, + { 241, "Status:" }, + { 242, "Subs" }, + { 243, "Vitesse des ST:" }, + { 244, "Sous-titres" }, + { 245, "Changement de personnage" }, + { 246, "Toucher pour un clic gauche, toucher deux fois pour un clic droit" }, + { 247, "Dialogue:" }, + { 248, "Le r\351pertoire s\351lectionn\351 est v\351rouill\351 en \351criture. S\351lectionnez un autre r\351pertoire." }, + { 249, "Th\350mes:" }, + { 250, "Th\350me:" }, + { 251, "Cet ID est d\351j\340 utilis\351 par un autre jeu. Choisissez en un autre svp." }, + { 252, "Le chargement de sauvegarde depuis le lanceur n'est pas support\351 pour ce jeu." }, + { 253, "Heure:" }, + { 254, "D\351passement du d\351lai lors de l'initialisation du r\351seau" }, + { 255, "D\351calage X du toucher" }, + { 256, "D\351callage Y du toucher" }, + { 257, "Mode touchpad d\351sactiv\351" }, + { 258, "Mode touchpad activ\351" }, + { 259, "Roland MT-32 exacte (d\351sactive l'\351mulation GM)" }, + { 260, "D\351sactiver la conversion des pistes MT-32 en General MIDI" }, + { 261, "Inconue" }, + { 262, "Erreur inconnue" }, + { 263, "D\351monter le DVD" }, + { 264, "D\351monter SMB" }, + { 265, "Sans changement d'\351chelle (vous devez faire d\351filer l'\351cran)" }, + { 266, "Mode de couleurs non support\351" }, + { 267, "Sauvegarde sans nom" }, + { 268, "Haut" }, + { 269, "Utiliser \340 la fois MIDI et AdLib" }, + { 270, "Activer le contr\364le du curseur de type trackpad" }, + { 271, "Nom d'utilisateur:" }, + { 272, "Utilise le pilote SDL" }, + { 273, "Underscan vertical:" }, + { 274, "Vid\351o" }, + { 275, "Clavier virtuel" }, + { 276, "Volume" }, + { 277, "MIDI Windows" }, + { 278, "Verrouill\351 en \351criture" }, + { 279, "Echec de l'\351criture des donn\351es" }, + { 280, "Oui" }, + { 281, "Vous devez relancer ScummVM pour que le changement soit pris en compte." }, + { 282, "Zone" }, + { 283, "Zoomer" }, + { 284, "D\351zoomer" }, + { 285, "Toutes les 10 mins" }, + { 286, "Toutes les 15 mins" }, + { 287, "Toutes les 30 mins" }, + { 288, "Toutes les 5 mins" }, + { 289, "\300 ~P~ropos" }, + { 290, "~A~jouter..." }, + { 291, "~A~nnuler" }, + { 292, "~F~ermer" }, + { 293, "~E~diter..." }, + { 294, "~A~ide" }, + { 295, "Contr\364le des combats d'~I~ndy" }, + { 296, "~T~ouches" }, + { 297, "Mode ~G~aucher" }, + { 298, "~C~harger" }, + { 299, "~C~harger" }, + { 300, "~S~uivant" }, + { 301, "~O~K" }, + { 302, "~O~ptions" }, + { 303, "~O~ptions..." }, + { 304, "~P~r\351c\351dent" }, + { 305, "~Q~uitter" }, + { 306, "~S~upprimer" }, + { 307, "~R~eprendre" }, + { 308, "Retour au ~L~anceur" }, + { 309, "~S~auver" }, + { 310, "~D~\351marrer" }, + { 311, "T~r~ansitions activ\351" }, + { 312, "~E~ffets de l'Eau Activ\351s" }, + { 313, "Mode ~Z~ip Activ\351" }, + { -1, NULL } +}; + +static const PoMessageEntry _translation_it_IT[] = { + { 0, "Project-Id-Version: ScummVM 1.2.0svn\nReport-Msgid-Bugs-To: scummvm-devel@lists.sf.net\nPOT-Creation-Date: 2010-07-12 17:44+0200\nPO-Revision-Date: 2010-06-30 23:56+0100\nLast-Translator: Maff <matteo.maff at gmail dot com>\nLanguage-Team: Italian\nLanguage: Italiano\nMIME-Version: 1.0\nContent-Type: text/plain; charset=iso-8859-1\nContent-Transfer-Encoding: 8bit\n" }, + { 1, " Sei sicuro di voler uscire? " }, + { 2, " (Attivo)" }, + { 3, " (Gioco)" }, + { 4, " (Globale)" }, + { 5, "(build creata il %s)" }, + { 6, ", errore nel montare la condivisione" }, + { 7, ", condivisione non montata" }, + { 8, "... progresso ..." }, + { 9, "11kHz" }, + { 10, "22 kHz" }, + { 11, "44 kHz" }, + { 12, "48 kHz" }, + { 13, "8 kHz" }, + { 14, "<predefinito>" }, + { 15, "Informazioni su ScummVM" }, + { 16, "Emulatore AdLib" }, + { 17, "Emulatore AdLib:" }, + { 18, "AdLib \350 utilizzato per la musica in molti giochi" }, + { 19, "Aggiungi gioco..." }, + { 20, "Renderer con antialiasing (16bpp)" }, + { 21, "Correzione proporzioni" }, + { 22, "Tasto associato: %s" }, + { 23, "Tasto associato: nessuno" }, + { 24, "Audio" }, + { 25, "Autosalva:" }, + { 26, "Motori disponibili:" }, + { 27, "~I~nfo..." }, + { 28, "Associa tasti" }, + { 29, "Entrambi" }, + { 30, "Luminosit\340:" }, + { 31, "Annulla" }, + { 32, "Impossibile creare il file" }, + { 33, "Modifica le opzioni di gioco" }, + { 34, "Modifica le opzioni globali di ScummVM" }, + { 35, "Seleziona se vuoi usare il dispositivo hardware audio compatibile con Roland che \350 connesso al tuo computer" }, + { 36, "Scegli" }, + { 37, "Scegli un'azione da mappare" }, + { 38, "Cancella" }, + { 39, "Chiudi" }, + { 40, "Corregge le proporzioni dei giochi 320x200" }, + { 41, "Impossibile trovare un motore in grado di eseguire il gioco selezionato" }, + { 42, "Modalit\340 video attuale:" }, + { 43, "Cursore gi\371" }, + { 44, "Cursore a sinistra" }, + { 45, "Cursore a destra" }, + { 46, "Cursore su" }, + { 47, "Emulatore OPL DOSBox" }, + { 48, "DVD" }, + { 49, "DVD montato con successo" }, + { 50, "DVD non montato" }, + { 51, "Data: " }, + { 52, "Debugger" }, + { 53, "Predefinito" }, + { 54, "Elimina" }, + { 55, "Disattiva spegnimento in chiusura" }, + { 56, "Grafica disattivata" }, + { 57, "Rilevati %d nuovi giochi..." }, + { 58, "Rilevati %d nuovi giochi." }, + { 59, "Visualizza " }, + { 60, "Mostra tastiera" }, + { 61, "Sei sicuro di voler eliminare questo salvataggio?" }, + { 62, "Sei sicuro di voler rimuovere questa configurazione di gioco?" }, + { 63, "Vuoi davvero eseguire il rilevatore di giochi in massa? Potrebbe aggiungere un numero enorme di giochi." }, + { 64, "Vuoi caricare o salvare il gioco?" }, + { 65, "Vuoi eseguire una scansione automatica?" }, + { 66, "Sei sicuro di voler uscire?" }, + { 67, "Double-strike" }, + { 68, "Gi\371" }, + { 69, "Attiva la modalit\340 Roland GS" }, + { 70, "Il motore non supporta il livello di debug '%s'" }, + { 71, "Inglese" }, + { 72, "Errore nell'esecuzione del gioco:" }, + { 73, "Errore nel montare il DVD" }, + { 74, "Percorso extra:" }, + { 75, "Emulatore FM Towns" }, + { 76, "Modalit\340 veloce" }, + { 77, "Funzionalit\340 compilate in:" }, + { 78, "Osservazione libera" }, + { 79, "Titolo completo del gioco" }, + { 80, "Modalit\340 a schermo intero" }, + { 81, "Accelerazione pad GC:" }, + { 82, "Sensibilit\340 pad GC:" }, + { 83, "Grafica" }, + { 84, "Dispositivo GM:" }, + { 85, "Lingua GUI:" }, + { 86, "Renderer GUI:" }, + { 87, "Gioco" }, + { 88, "Dati di gioco non trovati" }, + { 89, "ID di gioco non supportato" }, + { 90, "Percorso gioco:" }, + { 91, "Menu globale" }, + { 92, "Vai alla cartella superiore" }, + { 93, "Cartella superiore" }, + { 94, "Grafica" }, + { 95, "Modalit\340:" }, + { 96, "Ridimensionamento hardware (veloce, ma di bassa qualit\340)" }, + { 97, "Hercules ambra" }, + { 98, "Hercules verde" }, + { 99, "Nascondi la barra degli strumenti" }, + { 100, "Audio ad alta qualit\340 (pi\371 lento) (riavviare)" }, + { 101, "Valori pi\371 alti restituiscono un suono di maggior qualit\340, ma potrebbero non essere supportati dalla tua scheda audio" }, + { 102, "Tieni premuto Shift per l'aggiunta in massa" }, + { 103, "Underscan orizzontale:" }, + { 104, "Emulatore IBM PCjr" }, + { 105, "ID:" }, + { 106, "Avvia rete" }, + { 107, "Schermo in primo piano:" }, + { 108, "Avvio in corso dell'emulatore MT-32" }, + { 109, "Avvio rete in corso" }, + { 110, "Input" }, + { 111, "Percorso non valido" }, + { 112, "Programmatore tasti" }, + { 113, "Tastiera" }, + { 114, "Mappa tasti:" }, + { 115, "Tasti" }, + { 116, "Lingua dell'interfaccia grafica di ScummVM" }, + { 117, "Lingua del gioco. Un gioco inglese non potr\340 risultare tradotto in italiano" }, + { 118, "Lingua:" }, + { 119, "Sinistra" }, + { 120, "Clic sinistro" }, + { 121, "Carica" }, + { 122, "Carica gioco:" }, + { 123, "Carica un salvataggio del gioco selezionato" }, + { 124, "Emulatore OPL MAME" }, + { 125, "MIDI" }, + { 126, "Guadagno MIDI:" }, + { 127, "Disposit. MT32:" }, + { 128, "Emulatore MT-32" }, + { 129, "Schermo principale:" }, + { 130, "Mappa" }, + { 131, "Agg. in massa..." }, + { 132, "Menu" }, + { 133, "Varie" }, + { 134, "Modalit\340 mista AdLib/MIDI" }, + { 135, "Monta DVD" }, + { 136, "Monta SMB" }, + { 137, "Clic del mouse" }, + { 138, "Multifunzione" }, + { 139, "Dispositivo GM:" }, + { 140, "Volume musica:" }, + { 141, "Disattiva audio" }, + { 142, "Nome:" }, + { 143, "Rete disattivata" }, + { 144, "Rete non avviata (%d)" }, + { 145, "Rete attiva" }, + { 146, "Rete attiva, condivisione montata" }, + { 147, "Mai" }, + { 148, "No" }, + { 149, "Nessuna data salvata" }, + { 150, "Nessuna musica" }, + { 151, "Nessun tempo salvato" }, + { 152, "Nessun orario salvato" }, + { 153, "Nessuno" }, + { 154, "Normale (nessun ridimensionamento)" }, + { 155, "OK" }, + { 156, "Frequenza:" }, + { 157, "Ignora le impostazioni MIDI globali" }, + { 158, "Ignora le impostazioni audio globali" }, + { 159, "Ignora le impostazioni grafiche globali" }, + { 160, "Ignora le impostazioni globali di volume" }, + { 161, "Emulatore PC Speaker" }, + { 162, "Password:" }, + { 163, "Il percorso non \350 una cartella" }, + { 164, "Il percorso non \350 un file" }, + { 165, "Il percorso non esiste" }, + { 166, "Percorsi" }, + { 167, "Pausa" }, + { 168, "Scegli il gioco:" }, + { 169, "La piattaforma per la quale il gioco \350 stato concepito" }, + { 170, "Piattaforma:" }, + { 171, "Tempo di gioco: " }, + { 172, "Seleziona un'azione" }, + { 173, "Percorso plugin:" }, + { 174, "Disp. preferito:" }, + { 175, "Premi il tasto da associare" }, + { 176, "Esci" }, + { 177, "Chiudi ScummVM" }, + { 178, "Autorizzazione di lettura negata" }, + { 179, "Lettura fallita" }, + { 180, "Riprogramma tasti" }, + { 181, "Rimuove il gioco dalla lista. I file del gioco rimarranno intatti" }, + { 182, "Resa grafica:" }, + { 183, "Destra" }, + { 184, "Clic destro" }, + { 185, "Clic destro" }, + { 186, "Rotazione" }, + { 187, "Volume effetti:" }, + { 188, "SMB" }, + { 189, "Salva" }, + { 190, "Salvataggi:" }, + { 191, "Salvataggi:" }, + { 192, "Salva gioco:" }, + { 193, "Scansione completa!" }, + { 194, "%d cartelle analizzate..." }, + { 195, "Menu principale di ScummVM" }, + { 196, "ScummVM non ha potuto trovare un motore in grado di eseguire il gioco selezionato!" }, + { 197, "ScummVM non ha potuto trovare nessun gioco nella cartella specificata!" }, + { 198, "ScummVM non ha potuto aprire la cartella specificata!" }, + { 199, "Cerca nella lista dei giochi" }, + { 200, "Cerca:" }, + { 201, "Seleziona SoundFont" }, + { 202, "Seleziona un tema" }, + { 203, "Seleziona la cartella di gioco aggiuntiva" }, + { 204, "Seleziona un'azione e clicca 'Mappa'" }, + { 205, "Seleziona la cartella dei temi dell'interfaccia" }, + { 206, "Seleziona la cartella dei file aggiuntivi" }, + { 207, "Seleziona la cartella dei plugin" }, + { 208, "Seleziona la cartella dei salvataggi" }, + { 209, "Seleziona la cartella per i salvataggi" }, + { 210, "Seleziona la cartella contenente i file di gioco" }, + { 211, "Sensibilit\340" }, + { 212, "Server:" }, + { 213, "Condivisione:" }, + { 214, "Breve identificatore di gioco utilizzato per il riferimento a salvataggi e per l'esecuzione del gioco dalla riga di comando" }, + { 215, "Mostra tastiera" }, + { 216, "Mostra cursore del mouse" }, + { 217, "Mostra i sottotitoli e attiva le voci" }, + { 218, "Mostra/nascondi cursore" }, + { 219, "Salta" }, + { 220, "Salta battuta" }, + { 221, "Salta testo" }, + { 222, "Aggancia ai bordi" }, + { 223, "Ridimensionamento software (di buona qualit\340, ma pi\371 lento)" }, + { 224, "Suono on/off" }, + { 225, "SoundFont \350 supportato da alcune schede audio, Fluidsynth e Timidity" }, + { 226, "SoundFont:" }, + { 227, "Voci" }, + { 228, "Modalit\340 di resa grafica speciali supportate da alcuni giochi" }, + { 229, "Volume degli effetti sonori" }, + { 230, "Specifica il dispositivo audio predefinito per l'output General MIDI" }, + { 231, "Specifica il dispositivo audio predefinito per l'output Roland MT-32/LAPC1/CM32l/CM64" }, + { 232, "Specifica il dispositivo di output audio o l'emulatore della scheda audio" }, + { 233, "Specifica il percorso di ulteriori dati usati dai giochi o da ScummVM" }, + { 234, "Specifica il percorso di ulteriori dati usati dal gioco" }, + { 235, "Specifica il dispositivo audio o l'emulatore della scheda audio preferiti" }, + { 236, "Specifica dove archiviare i salvataggi" }, + { 237, "Voci" }, + { 238, "Volume voci:" }, + { 239, "Renderer standard (16bpp)" }, + { 240, "Esegue il gioco selezionato" }, + { 241, "Stato:" }, + { 242, "Sub" }, + { 243, "Velocit\340 testo:" }, + { 244, "Sottotitoli" }, + { 245, "Cambia personaggio" }, + { 246, "Un tocco per il clic sinistro, doppio tocco per il clic destro" }, + { 247, "Testo e voci:" }, + { 248, "La cartella scelta \350 in sola lettura. Si prega di sceglierne un'altra." }, + { 249, "Percorso tema:" }, + { 250, "Tema:" }, + { 251, "Questo ID di gioco \350 gi\340 in uso. Si prega di sceglierne un'altro." }, + { 252, "Questo gioco non supporta il caricamento di salvataggi dalla schermata di avvio." }, + { 253, "Ora: " }, + { 254, "Attesa per l'avvio della rete" }, + { 255, "Compensa X del tocco" }, + { 256, "Compensa Y del tocco" }, + { 257, "Modalit\340 touchpad disattivata." }, + { 258, "Modalit\340 touchpad attivata." }, + { 259, "Roland MT-32 effettivo (disattiva emulazione GM)" }, + { 260, "Disattiva la mappatura General MIDI per i giochi con colonna sonora Roland MT-32" }, + { 261, "Sconosciuto" }, + { 262, "Errore sconosciuto" }, + { 263, "Smonta DVD" }, + { 264, "Smonta SMB" }, + { 265, "Non ridimensionato (devi scorrere a sinistra e a destra)" }, + { 266, "Modalit\340 colore non supportata" }, + { 267, "Salvataggio senza titolo" }, + { 268, "Su" }, + { 269, "Utilizza generazione di suono sia MIDI che AdLib" }, + { 270, "Utilizza il controllo del cursore stile trackpad del portatile" }, + { 271, "Nome utente:" }, + { 272, "Utilizzo del driver SDL " }, + { 273, "Underscan verticale:" }, + { 274, "Video" }, + { 275, "Tastiera virtuale" }, + { 276, "Volume" }, + { 277, "MIDI Windows" }, + { 278, "Autorizzazione di scrittura negata" }, + { 279, "Scrittura dati fallita" }, + { 280, "S\354" }, + { 281, "Devi riavviare ScummVM affinch\351 le modifiche abbiano effetto." }, + { 282, "Zona" }, + { 283, "Zoom indietro" }, + { 284, "Zoom avanti" }, + { 285, "ogni 10 minuti" }, + { 286, "ogni 15 minuti" }, + { 287, "ogni 30 minuti" }, + { 288, "ogni 5 minuti" }, + { 289, "~I~nfo" }, + { 290, "~A~ggiungi gioco..." }, + { 291, "~A~nnulla" }, + { 292, "~C~hiudi" }, + { 293, "~M~odifica gioco..." }, + { 294, "~A~iuto" }, + { 295, "Controlli combattimento di ~I~ndy" }, + { 296, "~T~asti" }, + { 297, "~M~odalit\340 mancini" }, + { 298, "~C~arica" }, + { 299, "~C~arica..." }, + { 300, "~S~uccessivi" }, + { 301, "~O~K" }, + { 302, "~O~pzioni" }, + { 303, "~O~pzioni..." }, + { 304, "~P~recedenti" }, + { 305, "C~h~iudi" }, + { 306, "~R~imuovi gioco" }, + { 307, "~R~ipristina" }, + { 308, "~V~ai a schermata di avvio" }, + { 309, "~S~alva" }, + { 310, "~G~ioca" }, + { 311, "~T~ransizioni attive" }, + { 312, "~E~ffetto acqua attivo" }, + { 313, "Modalit\340 ~Z~ip attivata" }, + { -1, NULL } +}; + +static const PoMessageEntry _translation_ca_ES[] = { + { 0, "Project-Id-Version: ScummVM 1.2.0svn\nReport-Msgid-Bugs-To: scummvm-devel@lists.sf.net\nPOT-Creation-Date: 2010-07-12 17:44+0200\nPO-Revision-Date: 2010-06-26 16:45+0100\nLast-Translator: Jordi Vilalta Prat <jvprat@gmail.com>\nLanguage-Team: Catalan <scummvm-devel@lists.sf.net>\nLanguage: Catalan\nMIME-Version: 1.0\nContent-Type: text/plain; charset=iso-8859-1\nContent-Transfer-Encoding: 8bit\n" }, + { 2, " (Actiu)" }, + { 3, " (Joc)" }, + { 4, " (Global)" }, + { 5, "(compilat el %s)" }, + { 6, ", error al muntar la compartici\363" }, + { 7, ", compartici\363 no muntada" }, + { 8, "... progr\351s ..." }, + { 9, "11kHz" }, + { 10, "22 kHz" }, + { 11, "44 kHz" }, + { 12, "48 kHz" }, + { 13, "8 kHz" }, + { 14, "<per defecte>" }, + { 15, "Quant a ScummVM" }, + { 16, "Emulador d'AdLib" }, + { 17, "Emulador d'AdLib:" }, + { 18, "AdLib s'utilitza per la m\372sica de molts jocs" }, + { 19, "Afegeix Joc..." }, + { 20, "Pintat amb antialias (16bpp)" }, + { 21, "Correcci\363 del rati d'aspecte" }, + { 22, "Tecla associada : %s" }, + { 23, "Tecla associada : cap" }, + { 24, "\300udio" }, + { 25, "Desat autom\340tic:" }, + { 26, "Motors disponibles:" }, + { 27, "~Q~uant a..." }, + { 28, "Mapeja tecles" }, + { 29, "Ambd\363s" }, + { 30, "Brillantor:" }, + { 31, "Cancel\267la" }, + { 32, "No s'ha pogut crear el fitxer" }, + { 33, "Canvia les opcions del joc" }, + { 34, "Canvia les opcions globals de ScummVM" }, + { 35, "Marqueu si voleu utilitzar el vostre dispositiu hardware real de so compatible amb Roland connectat al vostre ordinador" }, + { 36, "Escull" }, + { 37, "Sel\267leccioneu una acci\363 per mapejar" }, + { 38, "Neteja el valor" }, + { 39, "Tanca" }, + { 40, "Corregeix la relaci\363 d'aspecte per jocs de 320x200" }, + { 41, "No s'ha pogut trobar cap motor capa\347 d'executar el joc seleccionat" }, + { 42, "Mode de v\355deo actual:" }, + { 43, "Cursor Avall" }, + { 44, "Cursor Esquerra" }, + { 45, "Cursor Dreta" }, + { 46, "Cursor Amunt" }, + { 47, "Emulador OPL de DOSBox" }, + { 48, "DVD" }, + { 49, "El DVD s'ha muntat satisfact\362riament" }, + { 50, "El DVD no est\340 muntat" }, + { 51, "Data: " }, + { 52, "Depurador" }, + { 53, "Per defecte" }, + { 54, "Suprimeix" }, + { 55, "Desactiva l'apagat autom\340tic" }, + { 56, "GFX desactivats" }, + { 57, "S'han descobert %d jocs nous ..." }, + { 58, "S'han descobert %d jocs nous." }, + { 59, "Pantalla" }, + { 60, "Mostra el teclat" }, + { 61, "Realment voleu suprimir aquesta partida?" }, + { 62, "Realment voleu suprimir la configuraci\363 d'aquest joc?" }, + { 63, "Esteu segur que voleu executar el detector massiu de jocs? Aix\362 pot afegir una gran quantitat de jocs." }, + { 64, "Voleu carregar o desar el joc?" }, + { 65, "Voleu fer una cerca autom\340tica?" }, + { 66, "Vols sortir?" }, + { 68, "Avall" }, + { 69, "Activa el Mode Roland GS" }, + { 70, "El motor no suporta el nivell de depuraci\363 '%s'" }, + { 71, "Angl\350s" }, + { 72, "Error al executar el joc:" }, + { 73, "Error al muntar el DVD" }, + { 74, "Cam\355 Extra:" }, + { 75, "Emulador de FM Towns" }, + { 76, "Mode r\340pid" }, + { 77, "Caracter\355stiques compilades:" }, + { 78, "Vista lliure" }, + { 79, "T\355tol complet del joc" }, + { 80, "Mode pantalla completa" }, + { 81, "Acceleraci\363 del Pad GC:" }, + { 82, "Sensibilitat del Pad GC:" }, + { 83, "GFX" }, + { 84, "Dispositiu GM:" }, + { 85, "Idioma de la interf\355cie d'usuari:" }, + { 86, "Mode de pintat de la interf\355cie d'usuari:" }, + { 87, "Joc" }, + { 88, "No s'han trobat les dades del joc" }, + { 89, "Identificador de joc no suportat" }, + { 90, "Cam\355 del Joc:" }, + { 91, "Men\372 global" }, + { 92, "Torna al nivell de directoris anterior" }, + { 93, "Amunt" }, + { 94, "Gr\340fics" }, + { 95, "Mode gr\340fic:" }, + { 96, "Escalat per hardware (r\340pid, per\362 de baixa qualitat)" }, + { 97, "Hercules \300mbar" }, + { 98, "Hercules Verd" }, + { 99, "Oculta la barra d'eines" }, + { 100, "Alta qualitat d'\340udio (m\351s lent) (reiniciar)" }, + { 101, "Valors m\351s alts especifiquen millor qualitat de so per\362 pot ser que la vostra tarja de so no ho suporti" }, + { 102, "Mantingueu premut Shift per a l'Addici\363 Massiva" }, + { 104, "Emulador d'IBM PCjr" }, + { 105, "Identificador:" }, + { 106, "Inicia la xarxa" }, + { 107, "Escalat inicial de la pantalla superior:" }, + { 108, "Iniciant l'Emulador de MT-32" }, + { 109, "Iniciant la xarxa" }, + { 110, "Entrada" }, + { 111, "Cam\355 incorrecte" }, + { 112, "Mapejador de tecles" }, + { 113, "Teclat" }, + { 114, "Mapa de teclat:" }, + { 115, "Tecles" }, + { 116, "Idioma de la interf\355cie d'usuari de ScummVM" }, + { 117, "Idioma del joc. Aix\362 no convertir\340 la vostra versi\363 Espanyola del joc a Angl\350s" }, + { 118, "Idioma:" }, + { 119, "Esquerra" }, + { 120, "Clic esquerre" }, + { 121, "Carrega" }, + { 122, "Carrega partida:" }, + { 123, "Carrega una partida pel joc seleccionat" }, + { 124, "Emulador OPL de MAME" }, + { 125, "MIDI" }, + { 126, "Guany MIDI:" }, + { 127, "Dispositiu MT32:" }, + { 128, "Emulador de MT-32" }, + { 129, "Escalat de la pantalla principal:" }, + { 130, "Mapeja" }, + { 131, "Addici\363 Massiva..." }, + { 132, "Men\372" }, + { 133, "Misc" }, + { 134, "Mode combinat AdLib/MIDI" }, + { 135, "Munta el DVD" }, + { 136, "Munta SMB" }, + { 137, "Clic del ratol\355" }, + { 138, "Funci\363 M\372ltiple" }, + { 139, "Dispositiu GM:" }, + { 140, "Volum de la m\372sica:" }, + { 141, "Silenciar tot" }, + { 142, "Nom:" }, + { 143, "Xarxa inactiva" }, + { 144, "Xarxa no iniciada (%d)" }, + { 145, "Xarxa activa" }, + { 146, "Xarxa activa, compartici\363 muntada" }, + { 147, "Mai" }, + { 148, "No" }, + { 149, "No hi ha data desada" }, + { 150, "Sense m\372sica" }, + { 151, "No hi ha temps de joc desat" }, + { 152, "No hi ha hora desada" }, + { 153, "Cap" }, + { 154, "Normal (sense escalar)" }, + { 155, "D'acord" }, + { 156, "Freq\374\350ncia de sortida:" }, + { 157, "Fer canvis sobre les opcions globals de MIDI" }, + { 158, "Fer canvis sobre les opcions globals d'\340udio" }, + { 159, "Fer canvis sobre les opcions globals de gr\340fics" }, + { 160, "Fer canvis sobre les opcions globals de volum" }, + { 161, "Emulador d'Altaveu de PC" }, + { 162, "Contrasenya:" }, + { 163, "El cam\355 no \351s un directori" }, + { 164, "El cam\355 no \351s un fitxer" }, + { 165, "El cam\355 no existeix" }, + { 166, "Camins" }, + { 167, "Pausa" }, + { 168, "Seleccioneu el joc:" }, + { 169, "Plataforma per la que el joc es va dissenyar originalment" }, + { 170, "Plataforma:" }, + { 171, "Temps de joc: " }, + { 172, "Seleccioneu una acci\363" }, + { 173, "Cam\355 dels connectors:" }, + { 174, "Dispositiu Preferit:" }, + { 175, "Premeu la tecla a associar" }, + { 176, "Surt" }, + { 177, "Surt de ScummVM" }, + { 178, "S'ha denegat el perm\355s de lectura" }, + { 179, "Ha fallat la lectura" }, + { 180, "Remapeja les tecles" }, + { 181, "Elimina un joc de la llista. Els fitxers de dades del joc es mantenen intactes" }, + { 182, "Mode de pintat:" }, + { 183, "Dreta" }, + { 184, "Clic dret" }, + { 185, "Clic dret" }, + { 186, "Rotar" }, + { 187, "Volum dels efectes:" }, + { 188, "SMB" }, + { 189, "Desa" }, + { 190, "Cam\355 de les Partides:" }, + { 191, "Cam\355 de les Partides: " }, + { 192, "Desa la partida:" }, + { 193, "S'ha acabat la cerca!" }, + { 194, "S'han cercat %d directoris ..." }, + { 195, "Men\372 Principal de ScummVM" }, + { 196, "ScummVM no ha pogut trobar cap motor capa\347 d'executar el joc seleccionat!" }, + { 197, "ScummVM no ha pogut trobar cap joc al directori especificat!" }, + { 198, "ScummVM no ha pogut obrir el directori especificat!" }, + { 199, "Cerca a la llista de jocs" }, + { 200, "Cerca:" }, + { 201, "Seleccioneu el fitxer SoundFont" }, + { 202, "Seleccioneu un Tema" }, + { 203, "Seleccioneu el directori addicional del joc" }, + { 204, "Seleccioneu una acci\363 i cliqueu 'Mapeja'" }, + { 205, "Seleccioneu el directori dels temes de la Interf\355cie d'Usuari" }, + { 206, "Seleccioneu el directori dels fitxers extra" }, + { 207, "Seleccioneu el directori dels connectors" }, + { 208, "Seleccioneu el directori de les partides desades" }, + { 209, "Seleccioneu el directori de les partides desades" }, + { 210, "Seleccioneu el directori amb les dades del joc" }, + { 211, "Sensibilitat" }, + { 212, "Servidor:" }, + { 213, "Compartici\363:" }, + { 214, "Identificador de joc curt utilitzat per referir-se a les partides i per executar el joc des de la l\355nia de comandes" }, + { 215, "Mostra el teclat" }, + { 216, "Mostra el cursor del ratol\355" }, + { 217, "Mostra els subt\355tols i reprodueix la veu" }, + { 218, "Mostra/Oculta el cursor" }, + { 219, "Salta" }, + { 220, "Salta la l\355nia" }, + { 221, "Salta el text" }, + { 223, "Escalat per software (bona qualitat, per\362 m\351s lent)" }, + { 224, "So engegat/parat" }, + { 225, "Algunes targes de so, Fluidsynth i Timidity suporten SoundFont" }, + { 226, "Fitxer SoundFont:" }, + { 227, "Veus" }, + { 228, "Modes de dispersi\363 especials suportats per alguns jocs" }, + { 229, "Volum dels sons d'efectes especials" }, + { 230, "Especifica el dispositiu de so per defecte per a la sortida General MIDI" }, + { 231, "Especifica el dispositiu de so per defecte per a la sortida de Roland MT-32/LAPC1/CM32l/CM64" }, + { 232, "Especifica el dispositiu de so o l'emulador de tarja de so de sortida" }, + { 233, "Especifica el cam\355 de les dades addicionals utilitzades per tots els jocs o pel ScummVM" }, + { 234, "Especifica el cam\355 de dades addicionals utilitzades pel joc" }, + { 235, "Especifica el dispositiu de so o l'emulador de tarja de so preferit" }, + { 236, "Especifica on es desaran les partides" }, + { 237, "Veus" }, + { 238, "Volum de la veu:" }, + { 239, "Pintat est\340ndard (16bpp)" }, + { 240, "Iniciant el joc seleccionat" }, + { 241, "Estat:" }, + { 242, "Subt" }, + { 243, "Velocitat dels subt\355tols:" }, + { 244, "Subt\355tols" }, + { 245, "Commuta el personatge" }, + { 246, "Toc per a clic esquerre, doble toc per a clic dret" }, + { 247, "Text i Veus:" }, + { 248, "No es pot escriure al directori seleccionat. Si us plau, escolliu-ne un altre." }, + { 249, "Cam\355 dels Temes:" }, + { 250, "Tema:" }, + { 251, "Aquest identificador de joc ja est\340 usat. Si us plau, trieu-ne un altre." }, + { 252, "Aquest joc no suporta la c\340rrega de partides des del llan\347ador." }, + { 253, "Hora: " }, + { 255, "Despla\347ament X del toc" }, + { 256, "Despla\347ament Y del toc" }, + { 257, "Mode Touchpad desactivat." }, + { 258, "Mode Touchpad activat." }, + { 259, "Roland MT-32 real (desactiva l'emulaci\363 GM)" }, + { 260, "Desactiva la conversi\363 General MIDI pels jocs que tenen banda sonora per a Roland MT-32" }, + { 261, "Desconegut" }, + { 262, "Error desconegut" }, + { 263, "Desmunta el DVD" }, + { 264, "Desmunta SMB" }, + { 265, "Sense escalar (haureu de despla\347ar-vos a esquerra i dreta)" }, + { 266, "Mode de color no suportat" }, + { 267, "Partida sense t\355tol" }, + { 268, "Amunt" }, + { 269, "Utilitza MIDI i la generaci\363 de so AdLib alhora" }, + { 270, "Utilitza el control del cursor a l'estil del trackpad dels port\340tils" }, + { 271, "Nom d'usuari:" }, + { 272, "Utilitzant el controlador SDL " }, + { 274, "V\355deo" }, + { 275, "Teclat virtual" }, + { 276, "Volum" }, + { 277, "MIDI de Windows" }, + { 278, "S'ha denegat el perm\355s d'escriptura" }, + { 279, "Ha fallat l'escriptura de dades" }, + { 280, "S\355" }, + { 281, "Heu de reiniciar ScummVM perqu\350 tots els canvis tingui efecte." }, + { 282, "Zona" }, + { 283, "Redueix" }, + { 284, "Amplia" }, + { 285, "cada 10 minuts" }, + { 286, "cada 15 minuts" }, + { 287, "cada 30 minuts" }, + { 288, "cada 5 minuts" }, + { 289, "~Q~uant a" }, + { 290, "~A~fegeix Joc..." }, + { 291, "~C~ancel\267la" }, + { 292, "~T~anca" }, + { 293, "~E~dita Joc..." }, + { 294, "~A~juda" }, + { 295, "Controls de lluita de l'~I~ndy" }, + { 296, "~T~ecles" }, + { 297, "Mode ~e~squerr\340" }, + { 298, "C~a~rrega" }, + { 299, "~C~arrega..." }, + { 300, "~S~eg\374ent" }, + { 301, "~D~'acord" }, + { 302, "~O~pcions" }, + { 303, "~O~pcions..." }, + { 304, "~A~nterior" }, + { 305, "~T~anca" }, + { 306, "~S~uprimeix Joc" }, + { 307, "~C~ontinua" }, + { 308, "~R~etorna al Llan\347ador" }, + { 309, "~D~esa" }, + { 310, "~I~nicia" }, + { 311, "~T~ransicions activades" }, + { 312, "~E~fecte de l'aigua activat" }, + { 313, "Mode ~Z~ip activat" }, + { -1, NULL } +}; + +static const PoMessageEntry _translation_hu_HU[] = { + { 0, "Project-Id-Version: ScummVM VERSION\nReport-Msgid-Bugs-To: scummvm-devel@lists.sf.net\nPOT-Creation-Date: 2010-07-12 17:44+0200\nPO-Revision-Date: 2009-11-25 07:42-0500\nLast-Translator: Alex Bevilacqua <alexbevi@gmail.com>\nLanguage-Team: Hungarian\nLanguage: \nMIME-Version: 1.0\nContent-Type: text/plain; charset=cp1250\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=(n != 1);\n" }, + { 14, "<alap\351rtelmezett>" }, + { 16, "AdLib vezet :" }, + { 17, "AdLib vezet :" }, + { 21, "Aspect adag korrekci\363" }, + { 24, "Hang" }, + { 25, "Automatikus ment\351s:" }, + { 28, "Kulcsok" }, + { 42, "Renderel\351si m\363d:" }, + { 53, "<alap\351rtelmezett>" }, + { 69, "K\351pess\351 Roland GS Mode" }, + { 74, "Extra \332tvonal:" }, + { 76, "Grafikus m\363d:" }, + { 80, "Teljes k\351perny s m\363d:" }, + { 86, "Lek\351pez eszk\366z GUI:" }, + { 90, "Extra \332tvonal:" }, + { 94, "Grafik\341val" }, + { 95, "Grafikus m\363d:" }, + { 115, "Kulcsok" }, + { 124, "AdLib vezet :" }, + { 126, "MIDI nyeres\351g:" }, + { 127, "Zene mennyis\351g:" }, + { 134, "Vegyes AdLib/MIDI m\363d" }, + { 139, "Zene mennyis\351g:" }, + { 140, "Zene mennyis\351g:" }, + { 141, "Muta \326sszes" }, + { 147, "Soha" }, + { 148, "Semmi" }, + { 153, "Semmi" }, + { 155, "Igen" }, + { 156, "Kimeneti teljes\355tm\351ny:" }, + { 166, "\326sv\351nyek" }, + { 167, "\326sv\351nyek" }, + { 182, "Renderel\351si m\363d:" }, + { 187, "SFX mennyis\351ge" }, + { 190, "Extra \332tvonal:" }, + { 212, "Soha" }, + { 237, "Csak a besz\351d" }, + { 238, "Besz\351d mennyis\351g:" }, + { 243, "Felirat sebess\351g:" }, + { 244, "Csak feliratok" }, + { 247, "Sz\366veg \351s besz\351d:" }, + { 250, "T\351ma:" }, + { 253, "T\351ma:" }, + { 259, "Igaz Roland MT-32 (megb\351n\355t GM emul\341ci\363)" }, + { 272, "Zenei vezet :" }, + { 276, "Volumene" }, + { 282, "Semmi" }, + { 285, "10 percenk\351nt" }, + { 286, "15 percenk\351nt" }, + { 287, "30 percenk\351nt" }, + { 288, "5 percenk\351nt" }, + { 296, "Kulcsok" }, + { 297, "Renderel\351si m\363d:" }, + { 301, "Igen" }, + { -1, NULL } +}; + +static const PoMessageEntry _translation_de_DE[] = { + { 0, "Project-Id-Version: ScummVM 1.2.0svn\nReport-Msgid-Bugs-To: scummvm-devel@lists.sf.net\nPOT-Creation-Date: 2010-07-12 17:44+0200\nPO-Revision-Date: 2010-07-09 20:37+0100\nLast-Translator: Simon Sawatzki\nLanguage-Team: Lothar Serra Mari <Lothar@Windowsbase.de> & Simon Sawatzki <SimSaw@gmx.de>\nLanguage: Deutsch\nMIME-Version: 1.0\nContent-Type: text/plain; charset=iso-8859-1\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=n != 1;\n" }, + { 1, " M\366chten Sie wirklich beenden? " }, + { 2, " (Aktiv)" }, + { 3, " (Spiel)" }, + { 4, " (Global)" }, + { 5, "(erstellt am %s)" }, + { 6, ", Fehler beim Einbinden des \366ffentlichen Verzeichnisses" }, + { 7, ", \366ffentliches Verzeichnis nicht eingebunden" }, + { 8, "... l\344uft..." }, + { 9, "11 kHz" }, + { 10, "22 kHz" }, + { 11, "44 kHz" }, + { 12, "48 kHz" }, + { 13, "8 kHz" }, + { 14, "<Standard>" }, + { 15, "\334ber ScummVM" }, + { 16, "AdLib-Emulator" }, + { 17, "AdLib-Emulator" }, + { 18, "AdLib wird f\374r die Musik in vielen Spielen verwendet." }, + { 19, "Spiel hinzuf\374gen" }, + { 20, "Kantengl\344ttung (16bpp)" }, + { 21, "Seitenverh\344ltnis korrigieren" }, + { 22, "Zugewiesene Taste: %s" }, + { 23, "Zugewiesene Taste: keine" }, + { 24, "Audio" }, + { 25, "Autom. Speichern:" }, + { 26, "Verf\374gbare Spiele-Engines:" }, + { 27, "\334be~r~" }, + { 28, "Tasten zuweisen" }, + { 29, "Beides" }, + { 30, "Helligkeit:" }, + { 31, "Abbrechen" }, + { 32, "Kann Datei nicht erstellen." }, + { 33, "Spieloptionen \344ndern" }, + { 34, "Globale ScummVM-Einstellungen bearbeiten" }, + { 35, "W\344hlen Sie dies aus, wenn Sie Ihre echte Hardware, die mit einer Roland-kompatiblen Soundkarte verbunden ist, verwenden m\366chten." }, + { 36, "Ausw\344hlen" }, + { 37, "Eine Aktion zum Zuweisen ausw\344hlen" }, + { 38, "Wert l\366schen" }, + { 39, "Schlie\337en" }, + { 40, "Seitenverh\344ltnis f\374r Spiele mit der Aufl\366sung 320x200 korrigieren" }, + { 41, "Kann keine Spiel-Engine finden, die dieses Spiel starten kann." }, + { 42, "Aktueller Videomodus:" }, + { 43, "Zeiger runter" }, + { 44, "Zeiger nach links" }, + { 45, "Zeiger nach rechts" }, + { 46, "Zeiger hoch" }, + { 47, "DOSBox-OPL-Emulator" }, + { 48, "DVD" }, + { 49, "DVD erfolgreich eingebunden" }, + { 50, "DVD nicht eingebunden" }, + { 51, "Datum: " }, + { 52, "Debugger" }, + { 53, "Standard" }, + { 54, "L\366schen" }, + { 55, "Stromsparmodus abschalten" }, + { 56, "GFX ausgeschalten" }, + { 57, "%d neue Spiele gefunden..." }, + { 58, "%d neue Spiele gefunden." }, + { 59, "Anzeige" }, + { 60, "Tastatur anzeigen" }, + { 61, "Diesen Spielstand wirklich l\366schen?" }, + { 62, "M\366chten Sie wirklich diese Spielkonfiguration entfernen?" }, + { 63, "M\366chten Sie wirklich den PC nach Spielen durchsuchen? M\366glicherweise wird dabei eine gr\366\337ere Menge an Spielen hinzugef\374gt." }, + { 64, "M\366chten Sie ein Spiel laden oder speichern?" }, + { 65, "M\366chten Sie eine automatische Durchsuchung vornehmen?" }, + { 66, "M\366chten Sie beenden?" }, + { 67, "Doppelzeilen (kein Zeilensprungverfahren)" }, + { 68, "Runter" }, + { 69, "Roland-GS-Modus" }, + { 70, "Engine unterst\374tzt den Debug-Level \"%s\" nicht" }, + { 71, "English" }, + { 72, "Fehler beim Ausf\374hren des Spiels:" }, + { 73, "Fehler beim Einbinden der DVD" }, + { 74, "Extrapfad:" }, + { 75, "FM-Towns-Emulator" }, + { 76, "Schneller Modus" }, + { 77, "Verwendete Funktionen:" }, + { 78, "Freie Ansicht" }, + { 79, "Voller Name des Spiels" }, + { 80, "Vollbildmodus" }, + { 81, "GC-Pad-Beschleunigung:" }, + { 82, "GC-Pad-Empfindlichkeit:" }, + { 83, "GFX" }, + { 84, "GM-Ger\344t:" }, + { 85, "GUI-Sprache:" }, + { 86, "GUI-Renderer:" }, + { 87, "Spiel" }, + { 88, "Spieldaten nicht gefunden" }, + { 89, "Spielkennung nicht unterst\374tzt" }, + { 90, "Spielpfad:" }, + { 91, "Hauptmen\374" }, + { 92, "Zu h\366herer Pfadebene wechseln" }, + { 93, "Pfad hoch" }, + { 94, "Grafik" }, + { 95, "Grafikmodus:" }, + { 96, "Hardware-Skalierung (schnell, aber schlechte Qualit\344t)" }, + { 97, "Hercules Bernsteingelb" }, + { 98, "Hercules-Gr\374n" }, + { 99, "Werkzeugleiste verbergen" }, + { 100, "Hohe Audioqualit\344t (lansamer) (erfordert Neustart)" }, + { 101, "H\366here Werte bewirken eine bessere Soundqualit\344t, werden aber m\366glicherweise nicht von jeder Soundkarte unterst\374tzt." }, + { 102, "Umschalttaste (Shift) gedr\374ckt halten, um Verzeichnisse nach Spielen zu durchsuchen" }, + { 103, "Horizontale Bildverkleinerung:" }, + { 104, "IBM-PCjr-Emulator" }, + { 105, "Kennung:" }, + { 106, "Netzwerk starten" }, + { 107, "Verg\366\337erung des oberen Bildschirms:" }, + { 108, "MT-32-Emulator wird gestartet..." }, + { 109, "Netzwerk wird gestartet..." }, + { 110, "Eingabe" }, + { 111, "Ung\374ltiges Verzeichnis" }, + { 112, "Tasten zuordnen" }, + { 113, "Tastatur" }, + { 114, "Tasten-Layout:" }, + { 115, "Tasten" }, + { 116, "Sprache der ScummVM-Oberfl\344che" }, + { 117, "Sprache des Spiels. Diese Funktion wird nicht eine spanische Version des Spiels in eine deutsche verwandeln." }, + { 118, "Sprache:" }, + { 119, "Links" }, + { 120, "Linksklick" }, + { 121, "Laden" }, + { 122, "Spiel laden:" }, + { 123, "Spielstand f\374r ausgew\344hltes Spiel laden" }, + { 124, "MAME-OPL-Emulator" }, + { 125, "MIDI" }, + { 126, "MIDI-Lautst\344rke:" }, + { 127, "MT32-Ger\344t:" }, + { 128, "MT-32-Emulation" }, + { 129, "Hauptbildschirm-Skalierung:" }, + { 130, "Zuweisen" }, + { 131, "Durchsuchen" }, + { 132, "Men\374" }, + { 133, "Sonstiges" }, + { 134, "AdLib-/MIDI-Modus" }, + { 135, "DVD einbinden" }, + { 136, "SMB einbinden" }, + { 137, "Mausklick" }, + { 138, "Multifunktion" }, + { 139, "Musikger\344t:" }, + { 140, "Musiklautst\344rke:" }, + { 141, "Alles aus" }, + { 142, "Name:" }, + { 143, "Netzwerk ist aus." }, + { 144, "Netzwerk nicht gestartet (%d)" }, + { 145, "Netzwerk gestartet" }, + { 146, "Netzwerk gestartet, \366ffentliches Verzeichnis eingebunden" }, + { 147, "Niemals" }, + { 148, "Nein" }, + { 149, "Kein Datum gespeichert" }, + { 150, "Keine Musik" }, + { 151, "Keine Spielzeit gespeichert" }, + { 152, "Keine Zeit gespeichert" }, + { 153, "-" }, + { 154, "Normal (keine Skalierung)" }, + { 155, "OK" }, + { 156, "Ausgabefrequenz:" }, + { 157, "Globale MIDI-Einstellungen \374bergehen" }, + { 158, "Globale Audioeinstellungen \374bergehen" }, + { 159, "Globale Grafikeinstellungen \374bergehen" }, + { 160, "Globale Lautst\344rke-Einstellungen \374bergehen" }, + { 161, "PC-Lautsprecher-Emulator" }, + { 162, "Passwort:" }, + { 163, "Ung\374ltiges Verzeichnis" }, + { 164, "Pfad ist keine Datei." }, + { 165, "Verzeichnis existiert nicht." }, + { 166, "Pfade" }, + { 167, "Pause" }, + { 168, "Spiel ausw\344hlen:" }, + { 169, "Plattform, f\374r die das Spiel urspr\374nglich erstellt wurde" }, + { 170, "Plattform:" }, + { 171, "Spieldauer: " }, + { 172, "Bitte eine Aktion ausw\344hlen" }, + { 173, "Plugin-Pfad:" }, + { 174, "Standard-Ger\344t:" }, + { 175, "Taste dr\374cken, um sie zuzuweisen" }, + { 176, "Beenden" }, + { 177, "ScummVM beenden" }, + { 178, "Lese-Berechtigung nicht vorhanden" }, + { 179, "Lesefehler aufgetreten" }, + { 180, "Tasten neu zuweisen" }, + { 181, "Spiel aus der Liste entfernen. Die Spieldateien bleiben erhalten." }, + { 182, "Render-Modus:" }, + { 183, "Rechts" }, + { 184, "Rechtsklick" }, + { 185, "Rechtsklick" }, + { 186, "Drehen" }, + { 187, "Effektlautst\344rke:" }, + { 188, "SMB" }, + { 189, "Speichern" }, + { 190, "Spielst\344nde:" }, + { 191, "Spielst\344nde: " }, + { 192, "Speichern:" }, + { 193, "Suchlauf abgeschlossen!" }, + { 194, "%d Ordner durchsucht..." }, + { 195, "ScummVM-Hauptmen\374" }, + { 196, "ScummVM konnte keine Engine finden, um das Spiel zu starten!" }, + { 197, "ScummVM kann in dem gew\344hlten Verzeichnis kein Spiel finden!" }, + { 198, "ScummVM kann das gew\344hlte Verzeichnis nicht \366ffnen!" }, + { 199, "In Spieleliste suchen" }, + { 200, "Suchen:" }, + { 201, "SoundFont ausw\344hlen" }, + { 202, "Thema ausw\344hlen" }, + { 203, "Verzeichnis mit zus\344tzlichen Dateien ausw\344hlen" }, + { 204, "Aktion ausw\344hlen und \"Zuweisen\" klicken" }, + { 205, "Verzeichnis f\374r Oberfl\344chen-Themen" }, + { 206, "Verzeichnis f\374r zus\344tzliche Dateien ausw\344hlen" }, + { 207, "Verzeichnis f\374r Erweiterungen ausw\344hlen" }, + { 208, "Verzeichnis f\374r Spielst\344nde ausw\344hlen" }, + { 209, "Verzeichnis f\374r Spielst\344nde ausw\344hlen" }, + { 210, "Verzeichnis mit Spieldateien ausw\344hlen" }, + { 211, "Empfindlichkeit" }, + { 212, "Server:" }, + { 213, "\326ffentliches Verzeichnis:" }, + { 214, "Kurzer Spielname, um die Spielst\344nde zuzuordnen und das Spiel von der Kommandozeile aus starten zu k\366nnen" }, + { 215, "Tastatur zeigen" }, + { 216, "Mauszeiger anzeigen" }, + { 217, "Untertitel anzeigen und Sprachausgabe aktivieren" }, + { 218, "Cursor zeigen/verbergen" }, + { 219, "\334berspringen" }, + { 220, "Zeile \374berspringen" }, + { 221, "Text \374berspringen" }, + { 222, "An Ecken anheften" }, + { 223, "Software-Skalierung (gute Qualit\344t, aber langsamer)" }, + { 224, "Ton ein/aus" }, + { 225, "SoundFont wird von einigen Soundkarten, Fluidsynth und Timidity unterst\374tzt." }, + { 226, "SoundFont:" }, + { 227, "Spr." }, + { 228, "Spezielle Farbmischungsmethoden werden von manchen Spielen unterst\374tzt." }, + { 229, "Lautst\344rke spezieller Soundeffekte" }, + { 230, "Legt das standardm\344\337ige Musikwiedergabe-Ger\344t f\374r General-MIDI-Ausgabe fest." }, + { 231, "Legt das standardm\344\337ige Tonwiedergabe-Ger\344t f\374r die Ausgabe von Roland MT-32/LAPC1/CM32l/CM64 fest." }, + { 232, "Legt das Musikwiedergabe-Ger\344t oder den Soundkarten-Emulator fest." }, + { 233, "Legt das Verzeichnis f\374r zus\344tzliche Spieldateien f\374r alle Spiele in ScummVM fest." }, + { 234, "Legt das Verzeichnis f\374r zus\344tzliche Spieldateien fest." }, + { 235, "Legt das bevorzugte Tonwiedergabe-Ger\344t oder den Soundkarten-Emulator fest." }, + { 236, "Legt fest, wo die Spielst\344nde abgelegt werden." }, + { 237, "Sprache" }, + { 238, "Sprachlautst\344rke:" }, + { 239, "Standard-Renderer (16bpp)" }, + { 240, "Ausgew\344hltes Spiel starten" }, + { 241, "Status:" }, + { 242, "Untert." }, + { 243, "Untertitel-Tempo:" }, + { 244, "Untertitel" }, + { 245, "Figur wechseln" }, + { 246, "Tippen f\374r Linksklick, Doppeltippen f\374r Rechtsklick" }, + { 247, "Text und Sprache:" }, + { 248, "In das gew\344hlte Verzeichnis kann nicht geschrieben werden. Bitte ein anderes ausw\344hlen." }, + { 249, "Themenpfad:" }, + { 250, "Thema:" }, + { 251, "Diese Spielkennung ist schon vergeben. Bitte eine andere w\344hlen." }, + { 252, "F\374r dieses Spiel wird das Laden aus der Spieleliste heraus nicht unterst\374tzt." }, + { 253, "Zeit: " }, + { 254, "Zeit\374berschreitung beim Starten des Netzwerks" }, + { 255, "Zu X-Position gehen" }, + { 256, "Zu Y-Position gehen" }, + { 257, "Touchpad-Modus ausgeschaltet." }, + { 258, "Touchpad-Modus aktiviert." }, + { 259, "Echte Roland-MT-32-Emulation (GM-Emulation deaktiviert)" }, + { 260, "Schaltet die General-MIDI-Zuweisung f\374r Spiele mit Roland-MT-32-Audiospur aus." }, + { 261, "Unbekannt" }, + { 262, "Unbekannter Fehler" }, + { 263, "DVD aush\344ngen" }, + { 264, "SMB aush\344ngen" }, + { 265, "Nicht skalieren (Sie m\374ssen nach links und nach rechts scrollen)" }, + { 266, "Farbmodus nicht unterst\374tzt" }, + { 267, "Unbenannt" }, + { 268, "Hoch" }, + { 269, "Benutzt MIDI und AdLib zur Sounderzeugung." }, + { 270, "Den Trackpad-Style f\374r Maussteuerung benutzen" }, + { 271, "Benutzername:" }, + { 272, "SDL-Treiber verwenden" }, + { 273, "Vertikale Bildverkleinerung:" }, + { 274, "Video" }, + { 275, "Virtuelle Tastatur" }, + { 276, "Lautst\344rke" }, + { 277, "Windows MIDI" }, + { 278, "Schreib-Berechtigung nicht vorhanden" }, + { 279, "Daten konnten nicht geschrieben werden." }, + { 280, "Ja" }, + { 281, "Sie m\374ssen ScummVM neustarten, um die Einstellungen zu \374bernehmen." }, + { 282, "Zone" }, + { 283, "Hineinzoomen" }, + { 284, "Herauszoomen" }, + { 285, "alle 10 Minuten" }, + { 286, "alle 15 Minuten" }, + { 287, "alle 30 Minuten" }, + { 288, "alle 5 Minuten" }, + { 289, "\334be~r~" }, + { 290, "Spiel ~h~inzuf\374gen" }, + { 291, "~A~bbrechen" }, + { 292, "~S~chlie\337en" }, + { 293, "Spielo~p~tionen" }, + { 294, "~H~ilfe" }, + { 295, "~K~ampfsteuerung f\374r Indiana Jones" }, + { 296, "~T~asten" }, + { 297, "~L~inke-Hand-Modus" }, + { 298, "~L~aden" }, + { 299, "~L~aden..." }, + { 300, "~W~eiter" }, + { 301, "~O~K" }, + { 302, "~O~ptionen" }, + { 303, "~O~ptionen" }, + { 304, "~Z~ur\374ck" }, + { 305, "~B~eenden" }, + { 306, "Spiel ~e~ntfernen" }, + { 307, "~F~ortsetzen" }, + { 308, "Zur Spiele~l~iste zur\374ck" }, + { 309, "~S~peichern" }, + { 310, "~S~tarten" }, + { 311, "\334ber~g~\344nge aktiviert" }, + { 312, "~W~assereffekt aktiviert" }, + { 313, "~Z~ip-Modus aktiviert" }, + { -1, NULL } +}; + +struct PoLangEntry { + const char *lang; + const char *charset; + const PoMessageEntry *msgs; +}; + +const PoLangEntry _translations[] = { + { "ru_RU", "iso-8859-5", _translation_ru_RU }, + { "fr_FR", "iso-8859-1", _translation_fr_FR }, + { "it_IT", "iso-8859-1", _translation_it_IT }, + { "ca_ES", "iso-8859-1", _translation_ca_ES }, + { "hu_HU", "cp1250", _translation_hu_HU }, + { "de_DE", "iso-8859-1", _translation_de_DE }, + { NULL, NULL, NULL } +}; + +// code + +static const PoMessageEntry *_currentTranslation = NULL; +static int _currentTranslationMessageEntryCount = 0; +static const char *_currentTranslationCharset = NULL; + +void po2c_setlang(const char *lang) { + _currentTranslation = NULL; + _currentTranslationMessageEntryCount = 0; + _currentTranslationCharset = NULL; + + // if lang is NULL or "", deactivate it + if (lang == NULL || *lang == '\0') + return; + + // searches for a valid language array + for (int i = 0; _currentTranslation == NULL && _translations[i].lang != NULL; ++i) { + if (strcmp(lang, _translations[i].lang) == 0) { + _currentTranslation = _translations[i].msgs; + _currentTranslationCharset = _translations[i].charset; + } + } + + // try partial searches + for (int i = 0; _currentTranslation == NULL && _translations[i].lang != NULL; ++i) { + if (strncmp(lang, _translations[i].lang, 2) == 0) { + _currentTranslation = _translations[i].msgs; + _currentTranslationCharset = _translations[i].charset; + } + } + + // if found, count entries + if (_currentTranslation != NULL) { + for (const PoMessageEntry *m = _currentTranslation; m->msgid != -1; ++m) + ++_currentTranslationMessageEntryCount; + } +} + +const char *po2c_gettext(const char *msgid) { + // if no language is set or msgid is empty, return msgid as is + if (_currentTranslation == NULL || *msgid == '\0') + return msgid; + + // binary-search for the msgid + int leftIndex = 0; + int rightIndex = _currentTranslationMessageEntryCount - 1; + + while (rightIndex >= leftIndex) { + const int midIndex = (leftIndex + rightIndex) / 2; + const PoMessageEntry * const m = &_currentTranslation[midIndex]; + + const int compareResult = strcmp(msgid, _messageIds[m->msgid]); + + if (compareResult == 0) + return m->msgstr; + else if (compareResult < 0) + rightIndex = midIndex - 1; + else + leftIndex = midIndex + 1; + } + + return msgid; +} + +const char *po2c_getcharset(void) { + if (_currentTranslationCharset) + return _currentTranslationCharset; + else + return "ASCII"; +} + +int po2c_getnumlangs(void) { + return ARRAYSIZE(_translations) - 1; +} + +const char *po2c_getlang(const int num) { + assert(num < ARRAYSIZE(_translations)); + return _translations[num].lang; +} diff --git a/common/module.mk b/common/module.mk index 83d30f0a9b..239f8e9ccf 100644 --- a/common/module.mk +++ b/common/module.mk @@ -22,6 +22,7 @@ MODULE_OBJS := \ system.o \ textconsole.o \ tokenizer.o \ + translation.o \ unarj.o \ unzip.o \ util.o \ diff --git a/common/savefile.h b/common/savefile.h index 39be661b45..16b0fdbfbe 100644 --- a/common/savefile.h +++ b/common/savefile.h @@ -109,14 +109,14 @@ public: /** * Open the savefile with the specified name in the given directory for saving. * @param name the name of the savefile - * @return pointer to an OutSaveFile, or NULL if an error occured. + * @return pointer to an OutSaveFile, or NULL if an error occurred. */ virtual OutSaveFile *openForSaving(const String &name) = 0; /** * Open the file with the specified name in the given directory for loading. * @param name the name of the savefile - * @return pointer to an InSaveFile, or NULL if an error occured. + * @return pointer to an InSaveFile, or NULL if an error occurred. */ virtual InSaveFile *openForLoading(const String &name) = 0; diff --git a/common/str.cpp b/common/str.cpp index 5e771c8b4d..744ba46ec7 100644 --- a/common/str.cpp +++ b/common/str.cpp @@ -105,8 +105,6 @@ String::String(char c) _storage[0] = c; _storage[1] = 0; - // TODO/FIXME: There is no reason for the following check -- we *do* - // allow strings to contain 0 bytes! _size = (c == 0) ? 0 : 1; } @@ -151,7 +149,11 @@ void String::ensureCapacity(uint32 new_size, bool keep_old) { // We need to allocate storage on the heap! // Compute a suitable new capacity limit - newCapacity = MAX(curCapacity * 2, computeCapacity(new_size+1)); + // If the current capacity is sufficient we use the same capacity + if (new_size < curCapacity) + newCapacity = curCapacity; + else + newCapacity = MAX(curCapacity * 2, computeCapacity(new_size+1)); // Allocate new storage newStorage = new char[newCapacity]; @@ -252,9 +254,11 @@ String &String::operator=(const String &str) { String &String::operator=(char c) { decRefCount(_extern._refCount); _str = _storage; - _size = 1; + _str[0] = c; _str[1] = 0; + + _size = (c == 0) ? 0 : 1; return *this; } diff --git a/common/str.h b/common/str.h index 189c37adb4..e3dec6cdc2 100644 --- a/common/str.h +++ b/common/str.h @@ -39,6 +39,9 @@ namespace Common { * Instead, small strings are stored 'inside' the string object (i.e. on * the stack, for stack allocated objects), and only for strings exceeding * a certain length do we allocate a buffer on the heap. + * + * The presence of \0 characters in the string will cause undefined + * behaviour in some operations. */ class String { protected: diff --git a/common/stream.cpp b/common/stream.cpp index 6737eafc9c..84b712a562 100644 --- a/common/stream.cpp +++ b/common/stream.cpp @@ -152,7 +152,7 @@ char *SeekableReadStream::readLine(char *buf, size_t bufSize) { len++; } - // We always terminate the buffer if no error occured + // We always terminate the buffer if no error occurred *p = 0; return buf; } @@ -303,4 +303,29 @@ bool BufferedSeekableReadStream::seek(int32 offset, int whence) { return true; // FIXME: STREAM REWRITE } +bool MemoryWriteStreamDynamic::seek(int32 offs, int whence) { + // Pre-Condition + assert(_pos <= _size); + switch (whence) { + case SEEK_END: + // SEEK_END works just like SEEK_SET, only 'reversed', + // i.e. from the end. + offs = _size + offs; + // Fall through + case SEEK_SET: + _ptr = _data + offs; + _pos = offs; + break; + + case SEEK_CUR: + _ptr += offs; + _pos += offs; + break; + } + // Post-Condition + assert(_pos <= _size); + + return true; // FIXME: STREAM REWRITE +} + } // End of namespace Common diff --git a/common/stream.h b/common/stream.h index 11041fa3ce..5e0d7149b0 100644 --- a/common/stream.h +++ b/common/stream.h @@ -687,6 +687,8 @@ public: uint32 size() const { return _size; } byte *getData() { return _data; } + + bool seek(int32 offset, int whence = SEEK_SET); }; } // End of namespace Common diff --git a/common/system.h b/common/system.h index b4b39889cd..6c8d6108a4 100644 --- a/common/system.h +++ b/common/system.h @@ -385,7 +385,7 @@ public: * @note Backends supporting RGB color should accept game data in RGB color * order, even if hardware uses BGR or some other color order. */ - virtual Common::List<Graphics::PixelFormat> getSupportedFormats() = 0; + virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const = 0; #else inline Graphics::PixelFormat getScreenFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); @@ -881,7 +881,7 @@ public: /** * Create a new mutex. - * @return the newly created mutex, or 0 if an error occured. + * @return the newly created mutex, or 0 if an error occurred. */ virtual MutexRef createMutex() = 0; diff --git a/common/textconsole.cpp b/common/textconsole.cpp index 87ba55ebf1..2e5a347489 100644 --- a/common/textconsole.cpp +++ b/common/textconsole.cpp @@ -47,6 +47,10 @@ extern bool isSmartphone(); #include <android/log.h> #endif +#ifdef __PSP__ + #include "backends/platform/psp/trace.h" +#endif + namespace Common { static OutputFormatter s_errorOutputFormatter = 0; @@ -159,6 +163,11 @@ void NORETURN_PRE error(const char *s, ...) { #ifdef __SYMBIAN32__ Symbian::FatalError(buf_output); #endif + +#ifdef __PSP__ + PspDebugTrace(false, "%s", buf_output); // write to file +#endif + // Finally exit. quit() will terminate the program if g_system is present if (g_system) g_system->quit(); diff --git a/common/translation.cpp b/common/translation.cpp new file mode 100644 index 0000000000..093f26510f --- /dev/null +++ b/common/translation.cpp @@ -0,0 +1,217 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +// winnt.h defines ARRAYSIZE, but we want our own one... - this is needed before including util.h +#undef ARRAYSIZE +#endif + +#include "translation.h" + +DECLARE_SINGLETON(Common::TranslationManager) + +#ifdef USE_DETECTLANG +#ifndef WIN32 +#include <locale.h> +#endif // !WIN32 +#endif + +#ifdef USE_TRANSLATION +#include "messages.cpp" +#endif + +namespace Common { + + +#ifdef USE_TRANSLATION + +// Translation enabled + +TranslationManager::TranslationManager() { +#ifdef USE_DETECTLANG +#ifdef WIN32 + // We can not use "setlocale" (at least not for MSVC builds), since it + // will return locales like: "English_USA.1252", thus we need a special + // way to determine the locale string for Win32. + char langName[9]; + char ctryName[9]; + + const LCID languageIdentifier = GetThreadLocale(); + + // GetLocalInfo is only supported starting from Windows 2000, according to this: + // http://msdn.microsoft.com/en-us/library/dd318101%28VS.85%29.aspx + // On the other hand the locale constants used, seem to exist on Windows 98 too, + // check this for that: http://msdn.microsoft.com/en-us/library/dd464799%28v=VS.85%29.aspx + // + // I am not exactly sure what is the truth now, it might be very well that this breaks + // support for systems older than Windows 2000.... + // + // TODO: Check whether this (or ScummVM at all ;-) works on a system with Windows 98 for + // example and if it does not and we still want Windows 9x support, we should definitly + // think of another solution. + if (GetLocaleInfo(languageIdentifier, LOCALE_SISO639LANGNAME, langName, sizeof(langName)) != 0 && + GetLocaleInfo(languageIdentifier, LOCALE_SISO3166CTRYNAME, ctryName, sizeof(ctryName)) != 0) { + _syslang = langName; + _syslang += "_"; + _syslang += ctryName; + } else { + _syslang = "C"; + } +#else // WIN32 + // Activating current locale settings + const char *locale = setlocale(LC_ALL, ""); + + // Detect the language from the locale + if (!locale) { + _syslang = "C"; + } else { + int length = 0; + + // Strip out additional information, like + // ".UTF-8" or the like. We do this, since + // our translation languages are usually + // specified without any charset information. + for (int i = 0; locale[i]; ++i) { + // TODO: Check whether "@" should really be checked + // here. + if (locale[i] == '.' || locale[i] == ' ' || locale[i] == '@') { + length = i; + break; + } + + length = i; + } + + _syslang = String(locale, length); + } +#endif // WIN32 +#else // USE_DETECTLANG + _syslang = "C"; +#endif // USE_DETECTLANG + + // Set the default language + setLanguage(""); +} + +TranslationManager::~TranslationManager() { +} + +void TranslationManager::setLanguage(const char *lang) { + if (*lang == '\0') + po2c_setlang(_syslang.c_str()); + else + po2c_setlang(lang); +} + +const char *TranslationManager::getTranslation(const char *message) { + return po2c_gettext(message); +} + +const char *TranslationManager::getCurrentCharset() { + return po2c_getcharset(); +} + +String TranslationManager::getTranslation(const String &message) { + return po2c_gettext(message.c_str()); +} + +const TLangArray TranslationManager::getSupportedLanguages() const { + TLangArray languages; + + int total = po2c_getnumlangs(); + for (int i = 0; i < total; i++) { + TLanguage lng(po2c_getlang(i), i + 1); + languages.push_back(lng); + } + + //sort(languages.begin(), languages.end()); + + return languages; +} + +int TranslationManager::parseLanguage(const String lang) { + int total = po2c_getnumlangs(); + + for (int i = 0; i < total; i++) { + if (lang == po2c_getlang(i)) + return i + 1; + } + + return kTranslationBuiltinId; +} + + +const char *TranslationManager::getLangById(int id) { + switch (id) { + case kTranslationAutodetectId: + return ""; + case kTranslationBuiltinId: + return "C"; + default: + if (id >= 0 && id - 1 < po2c_getnumlangs()) + return po2c_getlang(id - 1); + } + + // In case an invalid ID was specified, we will output a warning + // and return the same value as the auto detection id. + warning("Invalid language id %d passed to TranslationManager::getLangById", id); + return ""; +} + +#else // USE_TRANSLATION + +// Translation disabled + + +TranslationManager::TranslationManager() {} + +TranslationManager::~TranslationManager() {} + +void TranslationManager::setLanguage(const char *lang) {} + +const char *TranslationManager::getLangById(int id) { + return ""; +} + +int TranslationManager::parseLanguage(const String lang) { + return kTranslationBuiltinId; +} + +const char *TranslationManager::getTranslation(const char *message) { + return message; +} + +String TranslationManager::getTranslation(const String &message) { + return message; +} + +const TLangArray TranslationManager::getSupportedLanguages() const { + return TLangArray(); +} + +#endif // USE_TRANSLATION + +} // End of namespace Common diff --git a/common/translation.h b/common/translation.h new file mode 100644 index 0000000000..277ac6f5c4 --- /dev/null +++ b/common/translation.h @@ -0,0 +1,145 @@ +/* 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 COMMON_TRANSLATION_H +#define COMMON_TRANSLATION_H + +#include "common/singleton.h" +#include "common/str-array.h" + +namespace Common { + +enum TranslationIDs { + kTranslationAutodetectId = 0, + kTranslationBuiltinId = 1000 +}; + +struct TLanguage { + const char *name; + int id; + + TLanguage() { + name = 0; + id = 0; + } + + TLanguage(const char *n, int i) { + name = n; + id = i; + } +}; + +typedef Array<TLanguage> TLangArray; + +/** + * Message translation manager. + */ +class TranslationManager : public Singleton<TranslationManager> { +public: + /** + * The constructor detects the system language and sets default + * language to English. + */ + TranslationManager(); + ~TranslationManager(); + + /** + * Retrieves the language string to the given id. + * + * @param id Id of the language + * @return the matching string description of the language + */ + const char *getLangById(int id); + + /** + * Sets the current translation language to the one specified in the + * parameter. If the parameter is an empty string, it sets the default + * system language. + * + * @param lang Language to setup. + */ + void setLanguage(const char *lang); + + /** + * Sets the current translation language to the one specified by the + * id parameter. + * + * @param id The id of the language. + */ + void setLanguage(int id) { + setLanguage(getLangById(id)); + } + + /** + * Parses a language string and returns an id instead. + * + * @param lang Language string + * @return id of the language or kTranslationBuiltinId in case the + * language could not be found. + */ + int parseLanguage(const String lang); + + /** + * Returns the translation into the current language of the parameter + * message. In case the message isn't found in the translation catalog, + * it returns the original untranslated message. + */ + const char *getTranslation(const char *message); + + /** + * Returns the translation into the current language of the parameter + * message. In case the message isn't found in the translation catalog, + * it returns the original untranslated message. + */ + String getTranslation(const String &message); + + /** + * Returns a list of supported languages. + * + * @return The list of supported languages. + */ + const TLangArray getSupportedLanguages() const; + + /** + * Returns charset specified by selected translation language + */ + const char *getCurrentCharset(); + +private: + Common::String _syslang; +}; + +} // End of namespace Common + +#define TransMan Common::TranslationManager::instance() + +#ifdef USE_TRANSLATION +#define _(str) TransMan.getTranslation(str) +#else +#define _(str) str +#endif + +#define _s(str) str + +#endif diff --git a/common/unzip.cpp b/common/unzip.cpp index e46106025e..a29518a796 100644 --- a/common/unzip.cpp +++ b/common/unzip.cpp @@ -79,6 +79,30 @@ #include <zlib.h> #endif +#else // !USE_ZLIB + +// Even when zlib is not linked in, we can still open ZIP archives and read +// uncompressed files from them. Attempted decompression of compressed files +// will result in an error. +// +// Define the constants and types used by zlib. +#define Z_ERRNO -1 +#define Z_OK 0 +#define Z_DEFLATED 8 +typedef void *voidp; +typedef unsigned int uInt; +typedef unsigned long uLong; +typedef long z_off_t; +typedef unsigned char Byte; +typedef Byte Bytef; +typedef struct { + Bytef *next_in, *next_out; + uInt avail_in, avail_out; + uLong total_out; +} z_stream; + +#endif // !USE_ZLIB + #include "common/fs.h" #include "common/unzip.h" #include "common/file.h" @@ -1044,6 +1068,7 @@ int unzOpenCurrentFile (unzFile file) { pfile_in_zip_read_info->stream.total_out = 0; if (!Store) { +#ifdef USE_ZLIB pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; pfile_in_zip_read_info->stream.zfree = (free_func)0; pfile_in_zip_read_info->stream.opaque = (voidpf)0; @@ -1058,6 +1083,9 @@ int unzOpenCurrentFile (unzFile file) { * In unzip, i don't wait absolutely Z_STREAM_END because I known the * size of both compressed and uncompressed data */ +#else + err=UNZ_BADZIPFILE; +#endif } pfile_in_zip_read_info->rest_read_compressed = s->cur_file_info.compressed_size; pfile_in_zip_read_info->rest_read_uncompressed = s->cur_file_info.uncompressed_size; @@ -1068,9 +1096,8 @@ int unzOpenCurrentFile (unzFile file) { pfile_in_zip_read_info->stream.avail_in = (uInt)0; - s->pfile_in_zip_read = pfile_in_zip_read_info; - return UNZ_OK; + return err; } @@ -1143,9 +1170,11 @@ int unzReadCurrentFile(unzFile file, voidp buf, unsigned len) { for (i=0;i<uDoCopy;i++) *(pfile_in_zip_read_info->stream.next_out+i) = *(pfile_in_zip_read_info->stream.next_in+i); +#ifdef USE_ZLIB pfile_in_zip_read_info->crc32_data = crc32(pfile_in_zip_read_info->crc32_data, pfile_in_zip_read_info->stream.next_out, uDoCopy); +#endif // otherwise leave crc32_data as is and it won't be verified at the end pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; pfile_in_zip_read_info->stream.avail_in -= uDoCopy; pfile_in_zip_read_info->stream.avail_out -= uDoCopy; @@ -1154,6 +1183,7 @@ int unzReadCurrentFile(unzFile file, voidp buf, unsigned len) { pfile_in_zip_read_info->stream.total_out += uDoCopy; iRead += uDoCopy; } else { +#ifdef USE_ZLIB uLong uTotalOutBefore,uTotalOutAfter; const Bytef *bufBefore; uLong uOutThis; @@ -1184,6 +1214,11 @@ int unzReadCurrentFile(unzFile file, voidp buf, unsigned len) { return (iRead==0) ? UNZ_EOF : iRead; if (err!=Z_OK) break; +#else + // Cannot decompress the file without zlib. + err = UNZ_BADZIPFILE; + break; +#endif } } @@ -1302,16 +1337,20 @@ int unzCloseCurrentFile(unzFile file) { return UNZ_PARAMERROR; +#ifdef USE_ZLIB + // Only verify crc32_data when zlib is linked in, because otherwise crc32() is + // not defined. if (pfile_in_zip_read_info->rest_read_uncompressed == 0) { if (pfile_in_zip_read_info->crc32_data != pfile_in_zip_read_info->crc32_wait) err=UNZ_CRCERROR; } + if (pfile_in_zip_read_info->stream_initialised) + inflateEnd(&pfile_in_zip_read_info->stream); +#endif free(pfile_in_zip_read_info->read_buffer); pfile_in_zip_read_info->read_buffer = NULL; - if (pfile_in_zip_read_info->stream_initialised) - inflateEnd(&pfile_in_zip_read_info->stream); pfile_in_zip_read_info->stream_initialised = 0; free(pfile_in_zip_read_info); @@ -1466,5 +1505,3 @@ Archive *makeZipArchive(SeekableReadStream *stream) { } } // End of namespace Common - -#endif diff --git a/common/unzip.h b/common/unzip.h index 2f87a96d2b..c460840f12 100644 --- a/common/unzip.h +++ b/common/unzip.h @@ -25,8 +25,6 @@ #ifndef COMMON_UNZIP_H #define COMMON_UNZIP_H -#ifdef USE_ZLIB - namespace Common { class Archive; @@ -62,6 +60,4 @@ Archive *makeZipArchive(SeekableReadStream *stream); } // End of namespace Common -#endif // USE_ZLIB - #endif diff --git a/common/util.cpp b/common/util.cpp index 742eb0035d..521a12e4c7 100644 --- a/common/util.cpp +++ b/common/util.cpp @@ -24,6 +24,7 @@ #include "common/util.h" #include "common/system.h" +#include "common/translation.h" #include "common/config-manager.h" namespace Common { @@ -31,7 +32,7 @@ namespace Common { // // Print hexdump of the data passed in // -void hexdump(const byte * data, int len, int bytesPerLine, int startOffset) { +void hexdump(const byte *data, int len, int bytesPerLine, int startOffset) { assert(1 <= bytesPerLine && bytesPerLine <= 32); int i; byte c; @@ -106,29 +107,29 @@ bool parseBool(const Common::String &val, bool &valAsBool) { const LanguageDescription g_languages[] = { - {"zh-cn", "Chinese (China)", ZH_CNA}, - {"zh", "Chinese (Taiwan)", ZH_TWN}, - {"cz", "Czech", CZ_CZE}, - {"nl", "Dutch", NL_NLD}, - {"en", "English", EN_ANY}, // Generic English (when only one game version exist) - {"gb", "English (GB)", EN_GRB}, - {"us", "English (US)", EN_USA}, - {"fr", "French", FR_FRA}, - {"de", "German", DE_DEU}, - {"gr", "Greek", GR_GRE}, - {"he", "Hebrew", HE_ISR}, - {"hb", "Hebrew", HE_ISR}, // Deprecated - {"hu", "Hungarian", HU_HUN}, - {"it", "Italian", IT_ITA}, - {"jp", "Japanese", JA_JPN}, - {"kr", "Korean", KO_KOR}, - {"nb", "Norwegian Bokm\xE5l", NB_NOR}, - {"pl", "Polish", PL_POL}, - {"br", "Portuguese", PT_BRA}, - {"ru", "Russian", RU_RUS}, - {"es", "Spanish", ES_ESP}, - {"se", "Swedish", SE_SWE}, - {0, 0, UNK_LANG} + { "zh-cn", "Chinese (China)", ZH_CNA }, + { "zh", "Chinese (Taiwan)", ZH_TWN }, + { "cz", "Czech", CZ_CZE }, + { "nl", "Dutch", NL_NLD }, + { "en", "English", EN_ANY }, // Generic English (when only one game version exist) + { "gb", "English (GB)", EN_GRB }, + { "us", "English (US)", EN_USA }, + { "fr", "French", FR_FRA }, + { "de", "German", DE_DEU }, + { "gr", "Greek", GR_GRE }, + { "he", "Hebrew", HE_ISR }, + { "hb", "Hebrew", HE_ISR }, // Deprecated + { "hu", "Hungarian", HU_HUN }, + { "it", "Italian", IT_ITA }, + { "jp", "Japanese", JA_JPN }, + { "kr", "Korean", KO_KOR }, + { "nb", "Norwegian Bokm\xE5l", NB_NOR }, + { "pl", "Polish", PL_POL }, + { "br", "Portuguese", PT_BRA }, + { "ru", "Russian", RU_RUS }, + { "es", "Spanish", ES_ESP }, + { "se", "Swedish", SE_SWE }, + { 0, 0, UNK_LANG } }; Language parseLanguage(const String &str) { @@ -167,32 +168,32 @@ const char *getLanguageDescription(Language id) { const PlatformDescription g_platforms[] = { - {"2gs", "2gs", "2gs", "Apple IIgs", kPlatformApple2GS}, - {"3do", "3do", "3do", "3DO", kPlatform3DO}, - {"acorn", "acorn", "acorn", "Acorn", kPlatformAcorn}, - {"amiga", "ami", "amiga", "Amiga", kPlatformAmiga}, - {"atari", "atari-st", "st", "Atari ST", kPlatformAtariST}, - {"c64", "c64", "c64", "Commodore 64", kPlatformC64}, - {"pc", "dos", "ibm", "DOS", kPlatformPC}, - {"pc98", "pc98", "pc98", "PC-98", kPlatformPC98}, - {"wii", "wii", "wii", "Nintendo Wii", kPlatformWii}, - {"coco3", "coco3", "coco3", "CoCo3", kPlatformCoCo3}, + { "2gs", "2gs", "2gs", "Apple IIgs", kPlatformApple2GS }, + { "3do", "3do", "3do", "3DO", kPlatform3DO }, + { "acorn", "acorn", "acorn", "Acorn", kPlatformAcorn }, + { "amiga", "ami", "amiga", "Amiga", kPlatformAmiga }, + { "atari", "atari-st", "st", "Atari ST", kPlatformAtariST }, + { "c64", "c64", "c64", "Commodore 64", kPlatformC64 }, + { "pc", "dos", "ibm", "DOS", kPlatformPC }, + { "pc98", "pc98", "pc98", "PC-98", kPlatformPC98 }, + { "wii", "wii", "wii", "Nintendo Wii", kPlatformWii }, + { "coco3", "coco3", "coco3", "CoCo3", kPlatformCoCo3 }, // The 'official' spelling seems to be "FM-TOWNS" (e.g. in the Indy4 demo). // However, on the net many variations can be seen, like "FMTOWNS", // "FM TOWNS", "FmTowns", etc. - {"fmtowns", "towns", "fm", "FM-TOWNS", kPlatformFMTowns}, - - {"linux", "linux", "linux", "Linux", kPlatformLinux}, - {"macintosh", "mac", "mac", "Macintosh", kPlatformMacintosh}, - {"pce", "pce", "pce", "PC-Engine", kPlatformPCEngine}, - {"nes", "nes", "nes", "NES", kPlatformNES}, - {"segacd", "segacd", "sega", "SegaCD", kPlatformSegaCD}, - {"windows", "win", "win", "Windows", kPlatformWindows}, - {"playstation", "psx", "psx", "Sony PlayStation", kPlatformPSX}, - {"cdi", "cdi", "cdi", "Phillips CD-i", kPlatformCDi}, - - {0, 0, 0, "Default", kPlatformUnknown} + { "fmtowns", "towns", "fm", "FM-TOWNS", kPlatformFMTowns }, + + { "linux", "linux", "linux", "Linux", kPlatformLinux }, + { "macintosh", "mac", "mac", "Macintosh", kPlatformMacintosh }, + { "pce", "pce", "pce", "PC-Engine", kPlatformPCEngine }, + { "nes", "nes", "nes", "NES", kPlatformNES }, + { "segacd", "segacd", "sega", "SegaCD", kPlatformSegaCD }, + { "windows", "win", "win", "Windows", kPlatformWindows }, + { "playstation", "psx", "psx", "Sony PlayStation", kPlatformPSX }, + { "cdi", "cdi", "cdi", "Phillips CD-i", kPlatformCDi }, + + { 0, 0, 0, "Default", kPlatformUnknown } }; Platform parsePlatform(const String &str) { @@ -250,11 +251,11 @@ const char *getPlatformDescription(Platform id) { const RenderModeDescription g_renderModes[] = { - {"hercGreen", "Hercules Green", kRenderHercG}, - {"hercAmber", "Hercules Amber", kRenderHercA}, - {"cga", "CGA", kRenderCGA}, - {"ega", "EGA", kRenderEGA}, - {"amiga", "Amiga", kRenderAmiga}, + { "hercGreen", _s("Hercules Green"), kRenderHercG }, + { "hercAmber", _s("Hercules Amber"), kRenderHercA }, + { "cga", "CGA", kRenderCGA }, + { "ega", "EGA", kRenderEGA }, + { "amiga", "Amiga", kRenderAmiga }, {0, 0, kRenderDefault} }; @@ -293,12 +294,23 @@ const struct GameOpt { uint32 option; const char *desc; } g_gameOptions[] = { - { GUIO_NOSUBTITLES, "sndNoSubs" }, - { GUIO_NOMUSIC, "sndNoMusic" }, - { GUIO_NOSPEECH, "sndNoSpeech" }, - { GUIO_NOSFX, "sndNoSFX" }, - { GUIO_NOMIDI, "sndNoMIDI" }, + { GUIO_NOSUBTITLES, "sndNoSubs" }, + { GUIO_NOMUSIC, "sndNoMusic" }, + { GUIO_NOSPEECH, "sndNoSpeech" }, + { GUIO_NOSFX, "sndNoSFX" }, + { GUIO_NOMIDI, "sndNoMIDI" }, + { GUIO_NOLAUNCHLOAD, "launchNoLoad" }, + + { GUIO_MIDIPCSPK, "midiPCSpk" }, + { GUIO_MIDICMS, "midiCMS" }, + { GUIO_MIDIPCJR, "midiPCJr" }, + { GUIO_MIDIADLIB, "midiAdLib" }, + { GUIO_MIDITOWNS, "midiTowns" }, + { GUIO_MIDIPC98, "midiPC98" }, + { GUIO_MIDIMT32, "midiMt32" }, + { GUIO_MIDIGM, "midiGM" }, + { GUIO_NONE, 0 } }; @@ -314,9 +326,26 @@ bool checkGameGUIOption(GameGUIOption option, const String &str) { return false; } +bool checkGameGUIOptionLanguage(Language lang, const String &str) { + if (!str.contains("lang_")) // If no languages are specified + return true; + + if (str.contains(getGameGUIOptionsDescriptionLanguage(lang))) + return true; + + return false; +} + +const String getGameGUIOptionsDescriptionLanguage(Language lang) { + if (lang == UNK_LANG) + return ""; + + return String(String("lang_") + getLanguageDescription(lang)); +} + uint32 parseGameGUIOptions(const String &str) { uint32 res = 0; - + for (int i = 0; g_gameOptions[i].desc; i++) if (str.contains(g_gameOptions[i].desc)) res |= g_gameOptions[i].option; @@ -324,7 +353,7 @@ uint32 parseGameGUIOptions(const String &str) { return res; } -String getGameGUIOptionsDescription(uint32 options) { +const String getGameGUIOptionsDescription(uint32 options) { String res = ""; for (int i = 0; g_gameOptions[i].desc; i++) @@ -336,12 +365,15 @@ String getGameGUIOptionsDescription(uint32 options) { return res; } -void updateGameGUIOptions(const uint32 options) { +void updateGameGUIOptions(const uint32 options, const String &langOption) { + const String newOptionString = getGameGUIOptionsDescription(options) + " " + langOption; + if ((options && !ConfMan.hasKey("guioptions")) || - (ConfMan.hasKey("guioptions") && options != parseGameGUIOptions(ConfMan.get("guioptions")))) { - ConfMan.set("guioptions", getGameGUIOptionsDescription(options)); + (ConfMan.hasKey("guioptions") && ConfMan.get("guioptions") != newOptionString)) { + ConfMan.set("guioptions", newOptionString); ConfMan.flushToDisk(); } } -} // End of namespace Common +} // End of namespace Common + diff --git a/common/util.h b/common/util.h index 0b7a44f5b3..7a9cf4fb2d 100644 --- a/common/util.h +++ b/common/util.h @@ -215,21 +215,32 @@ enum GameGUIOption { GUIO_NOSUBTITLES = (1 << 0), GUIO_NOMUSIC = (1 << 1), GUIO_NOSPEECH = (1 << 2), - GUIO_NOSFX = (1 << 3), - GUIO_NOMIDI = (1 << 4), - GUIO_NOLAUNCHLOAD = (1 << 5) + GUIO_NOSFX = (1 << 3), + GUIO_NOMIDI = (1 << 4), + GUIO_NOLAUNCHLOAD = (1 << 5), + + GUIO_MIDIPCSPK = (1 << 6), + GUIO_MIDICMS = (1 << 7), + GUIO_MIDIPCJR = (1 << 8), + GUIO_MIDIADLIB = (1 << 9), + GUIO_MIDITOWNS = (1 << 10), + GUIO_MIDIPC98 = (1 << 11), + GUIO_MIDIMT32 = (1 << 12), + GUIO_MIDIGM = (1 << 13) }; bool checkGameGUIOption(GameGUIOption option, const String &str); +bool checkGameGUIOptionLanguage(Language lang, const String &str); uint32 parseGameGUIOptions(const String &str); -String getGameGUIOptionsDescription(uint32 options); +const String getGameGUIOptionsDescription(uint32 options); +const String getGameGUIOptionsDescriptionLanguage(Language lang); /** * Updates the GUI options of the current config manager * domain, when they differ to the ones passed as * parameter. */ -void updateGameGUIOptions(const uint32 options); +void updateGameGUIOptions(const uint32 options, const String &langOption); } // End of namespace Common @@ -136,6 +136,8 @@ _enable_prof=no # Default vkeybd/keymapper options _vkeybd=no _keymapper=no +# GUI translation options +_translation=yes # Default platform settings _backend=sdl _endian=unknown @@ -341,7 +343,7 @@ get_system_exe_extension() { arm-riscos) _exeext=",ff8" ;; - dreamcast | gamecube | nds | ps2 | psp | wii) + dreamcast | gamecube | ds | ps2 | psp | wii) _exeext=".elf" ;; gp2x-linux) @@ -625,7 +627,7 @@ Usage: $0 [OPTIONS]... Configuration: -h, --help display this help and exit --backend=BACKEND backend to build (dc, gp2x, gp2xwiz, iphone, - linuxmoto, nds, null, ps2, psp, sdl, wii, wince) + linuxmoto, ds, null, ps2, psp, sdl, wii, wince) [sdl] Installation directories: @@ -655,7 +657,7 @@ Special configuration feature: gamecube for Nintendo GameCube iphone for Apple iPhone linupy for Yopy PDA - nds for Nintendo DS + ds for Nintendo DS ps2 for PlayStation 2 psp for PlayStation Portable wii for Nintendo Wii @@ -676,6 +678,7 @@ Optional Features: --disable-16bit don't enable 16bit color support --disable-scalers exclude scalers --disable-hq-scalers exclude HQ2x and HQ3x scalers + --disable-translation don't build support for translated messages --enable-text-console use text console instead of graphical console --enable-verbose-build enable regular echoing of commands during build process @@ -760,6 +763,8 @@ for ac_option in $@; do --default-dynamic) _plugins_default=dynamic ;; --enable-mt32emu) _mt32emu=yes ;; --disable-mt32emu) _mt32emu=no ;; + --enable-translation) _translation=yes ;; + --disable-translation) _translation=no ;; --enable-vkeybd) _vkeybd=yes ;; --disable-vkeybd) _vkeybd=no ;; --enable-keymapper) _keymapper=yes ;; @@ -944,8 +949,8 @@ motomagx) _host_cpu=arm _host_alias=arm-linux-gnueabi ;; -nds) - _host_os=nds +ds) + _host_os=ds _host_cpu=arm _host_alias=arm-eabi ;; @@ -1002,7 +1007,7 @@ wince) android) _host_os=android _host_cpu=arm - _host_alias=arm-android-eabi + _host_alias=arm-oe-linux-androideabi ;; *) if test -n "$_host"; then @@ -1037,7 +1042,9 @@ fi if test "$_release_build" = yes; then # Release mode enabled: enable optimizations. This also # makes it possible to use -Wuninitialized, so let's do that. - CXXFLAGS="$CXXFLAGS -O2 -Wuninitialized" + # We will also add a define, which indicates we are doing + # an build for a release version. + CXXFLAGS="$CXXFLAGS -O2 -Wuninitialized -DRELEASE_BUILD" fi @@ -1063,7 +1070,7 @@ esac # Platform specific sanity checks # case $_host_os in -gamecube | nds | wii) +gamecube | ds | wii) if test -z "$DEVKITPRO"; then echo "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to devkitPRO>" exit 1 @@ -1131,9 +1138,12 @@ else CXX= for compiler in $compilers; do if test_compiler $compiler; then + echo "success testing compiler: $1" >> "$TMPLOG" CXX=$compiler echo $CXX break + else + echo "failure testing compiler: $1" >> "$TMPLOG" fi done fi @@ -1351,7 +1361,8 @@ case $_host_os in CXXFLAGS="$CXXFLAGS -Os -mogc -mcpu=750 -meabi -mhard-float" CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections -fmodulo-sched" CXXFLAGS="$CXXFLAGS -I$DEVKITPRO/libogc/include -I$DEVKITPRO/cube/include" - LDFLAGS="$LDFLAGS -mogc -mcpu=750 -L$DEVKITPRO/libogc/lib/cube -L$DEVKITPRO/cube/lib" + # libogc is required to link the cc tests (includes _start()) + LDFLAGS="$LDFLAGS -mogc -mcpu=750 -L$DEVKITPRO/libogc/lib/cube -L$DEVKITPRO/cube/lib -logc" ;; haiku*) DEFINES="$DEFINES -DUNIX -DSYSTEM_NOT_SUPPORTING_D_TYPE" @@ -1380,9 +1391,14 @@ case $_host_os in mint*) DEFINES="$DEFINES -DUNIX -DSYSTEM_NOT_SUPPORTING_D_TYPE" ;; - nds) - # TODO nds + ds) + # TODO Nintendo DS DEFINES="$DEFINES -D__DS__ -DNDS -DARM9 -DARM -DNONSTANDARD_PORT" + CXXFLAGS="$CXXFLAGS -isystem $DEVKITPRO/libnds/include -isystem $DEVKITPRO/devkitARM/arm-eabi/include" + CXXFLAGS="$CXXFLAGS -mthumb-interwork -ffunction-sections -fdata-sections -fno-strict-aliasing" + LDFLAGS="$LDFLAGS -specs=ds_arm9.specs -mthumb-interwork -mno-fpu -Wl,-Map,map.txt -Wl,--gc-sections" + LDFLAGS="$LDFLAGS -L$DEVKITPRO/libnds/lib" + LIBS="$LIBS -lnds9" ;; os2-emx*) DEFINES="$DEFINES -DUNIX" @@ -1404,7 +1420,8 @@ case $_host_os in CXXFLAGS="$CXXFLAGS -Os -mrvl -mcpu=750 -meabi -mhard-float" CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections -fmodulo-sched" CXXFLAGS="$CXXFLAGS -I$DEVKITPRO/libogc/include -I$DEVKITPRO/wii/include" - LDFLAGS="$LDFLAGS -mrvl -mcpu=750 -L$DEVKITPRO/libogc/lib/wii -L$DEVKITPRO/wii/lib" + # libogc is required to link the cc tests (includes _start()) + LDFLAGS="$LDFLAGS -mrvl -mcpu=750 -L$DEVKITPRO/libogc/lib/wii -L$DEVKITPRO/wii/lib -logc" ;; wince) CXXFLAGS="$CXXFLAGS -O3 -march=armv4 -mtune=xscale" @@ -1486,6 +1503,7 @@ if test -n "$_host"; then _build_hq_scalers="no" _mt32emu="no" _vkeybd="yes" + _port_mk="backends/platform/gp2x/gp2x-bundle.mk" ;; gp2xwiz) DEFINES="$DEFINES -DUNIX -DGP2XWIZ -DNDEBUG" @@ -1501,6 +1519,7 @@ if test -n "$_host"; then _build_hq_scalers="no" _mt32emu="no" _vkeybd="yes" + _port_mk="backends/platform/gp2xwiz/gp2xwiz-bundle.mk" ;; iphone) DEFINES="$DEFINES -DIPHONE -DUNIX" @@ -1557,24 +1576,23 @@ if test -n "$_host"; then _vkeybd="yes" _port_mk="backends/platform/linuxmoto/linuxmoto.mk" ;; - nds) + ds) # TODO: complete this - # TODO: Maybe rename nds -> ds (would be more consistent with other backends) DEFINES="$DEFINES -DDISABLE_FANCY_THEMES -DVECTOR_RENDERER_FORMAT=1555" DEFINES="$DEFINES -DDISABLE_DEFAULT_SAVEFILEMANAGER" - DEFINES="$DEFINES -DREDUCE_MEMORY_USAGE" + DEFINES="$DEFINES -DREDUCE_MEMORY_USAGE -DSTREAM_AUDIO_FROM_DISK" + DEFINES="$DEFINES -DDISABLE_DOSBOX_OPL" DEFINES="$DEFINES -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE" _need_memalign=yes - _backend="nds" + 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_COSTUME_ASM = 1' + add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1' + _backend="ds" _build_hq_scalers="no" _mt32emu="no" _port_mk="backends/platform/ds/ds.mk" - # TODO: Enable more ARM optimizations -- requires testing! - 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_COSTUME_ASM = 1' - #add_line_to_config_mk 'USE_ARM_SCALER_ASM = 1' ;; neuros) DEFINES="$DEFINES -DUNIX -DNEUROS" @@ -1666,7 +1684,6 @@ if test -n "$_host"; then ;; 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' @@ -1675,7 +1692,6 @@ if test -n "$_host"; then 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" @@ -1978,7 +1994,7 @@ add_to_config_mk_if_yes "$_indeo3" 'USE_INDEO3 = 1' cat > $TMPC << EOF int main(void) { return 0; } EOF -cc_check -lm && LDFLAGS="$LDFLAGS -lm" +cc_check -lm && LIBS="$LIBS -lm" # # Check for Ogg Vorbis @@ -2314,6 +2330,31 @@ if test "$_keymapper" = yes ; then DEFINES="$DEFINES -DENABLE_KEYMAPPER" fi +# Check whether to build translation support +# +echo_n "Building translation support... " +add_to_config_mk_if_yes $_translation 'USE_TRANSLATION = 1' +add_to_config_h_if_yes $_translation '#define USE_TRANSLATION' +if test "$_translation" = no ; then + echo "no" +else + echo_n "yes (" + + cat > $TMPC << EOF +#include <locale.h> +int main(void) { setlocale(LC_ALL, ""); return 0; } +EOF + _detectlang=no + cc_check $LDFLAGS $CXXFLAGS && _detectlang=yes + + add_to_config_h_if_yes $_detectlang '#define USE_DETECTLANG' + if test "$_detectlang" = yes ; then + echo "with runtime language detection)" + else + echo "without runtime language detection)" + fi +fi + # # Figure out installation directories # @@ -2408,8 +2449,11 @@ case $_backend in LIBS="$LIBS `$_sdlconfig --prefix="$_sdlpath" --libs`" DEFINES="$DEFINES -DSDL_BACKEND -DLINUXMOTO" ;; - nds) - # TODO nds + ds) + # TODO ds + INCLUDES="$INCLUDES "'-I$(srcdir)/backends/platform/ds/arm9/source' + INCLUDES="$INCLUDES "'-I$(srcdir)/backends/platform/ds/commoninclude' + INCLUDES="$INCLUDES "'-Ibackends/platform/ds/arm9/data' ;; null) DEFINES="$DEFINES -DUSE_NULL_DRIVER" @@ -2424,14 +2468,7 @@ case $_backend in ;; psp) DEFINES="$DEFINES -D__PSP__ -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE -DDISABLE_DOSBOX_OPL" - INCLUDES="$INCLUDES -I$PSPDEV/psp/include/SDL" - LIBS="$LIBS -lpng -lSDL -Wl,-Map,mapfile.txt" - SDLLIBS=`$PSPDEV/psp/bin/sdl-config --libs` - - if `echo "$SDLLIBS" | grep ".*-lGL.*" 1>/dev/null 2>&1` - then - LIBS="$LIBS -lGL" - fi + LIBS="$LIBS -lpng -Wl,-Map,mapfile.txt" ;; samsungtv) find_sdlconfig @@ -2463,12 +2500,36 @@ case $_backend in LIBS="$LIBS -static -lSDL" ;; android) + static_libs='' + system_libs='' + for lib in $LIBS; do + case $lib in + -lz|-lm) + system_libs="$system_libs $lib" + ;; + *) + static_libs="$static_libs $lib" + ;; + esac + done + # -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" + LIBS="-Wl,-Bstatic $static_libs -Wl,-Bdynamic -lgcc $system_libs -lstdc++ -llog -lGLESv1_CM" DEFINES="$DEFINES -D__ANDROID__ -DANDROID_BACKEND -DREDUCE_MEMORY_USAGE" add_line_to_config_mk 'PLUGIN_LDFLAGS += $(LDFLAGS) -Wl,-shared,-Bsymbolic' + + # Work around an Android 2.0+ run-time linker bug: + # The linker doesn't actually look in previously + # loaded libraries when trying to resolve symbols - + # effectively turning all dlopen(RTLD_GLOBAL) calls + # into dlopen(RTLD_LOCAL). It *does* look in + # DT_NEEDED libraries, so the workaround is to add an + # (otherwise unnecessary) dependency from plugins back + # to the main libscummvm.so. + add_line_to_config_mk 'PLUGIN_LDFLAGS += -Lbuild.tmp -lscummvm' + add_line_to_config_mk 'PLUGIN_EXTRA_DEPS += build.tmp/libscummvm.so' ;; *) echo "support for $_backend backend not implemented in configure script yet" @@ -2485,7 +2546,7 @@ if test "$have_gcc" = yes ; then case $_host_os in # newlib-based system include files suppress non-C89 function # declarations under __STRICT_ANSI__ - mingw* | dreamcast | wii | gamecube | psp | wince | amigaos* | android) + mingw* | dreamcast | wii | gamecube | ds | psp | wince | amigaos* | android) CXXFLAGS="$CXXFLAGS -W -Wno-unused-parameter" ;; *) diff --git a/dists/android/AndroidManifest.xml b/dists/android/AndroidManifest.xml new file mode 100644 index 0000000000..55e3bf2f38 --- /dev/null +++ b/dists/android/AndroidManifest.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="utf-8"?> <!-- -*- xml -*- --> +<!-- NB: android:versionCode needs to be bumped for formal releases --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.inodes.gus.scummvm" + android:versionCode="6" android:versionName="1.2.0svn" + android:installLocation="preferExternal"> + + <!-- This version is built against a cupcake (and newer?) ABI. + It works on Android 1.5 (SDK 3) and newer. + --> + <uses-sdk android:minSdkVersion="3" + android:targetSdkVersion="8" /> + + <application android:name=".ScummVMApplication" + android:label="@string/app_name" + android:description="@string/app_desc" + android:icon="@drawable/scummvm" + android:persistent="true"> + <activity android:name=".ScummVMActivity" + android:theme="@android:style/Theme.NoTitleBar.Fullscreen" + android:screenOrientation="landscape" + android:configChanges="orientation|keyboardHidden" + android:windowSoftInputMode="adjustResize"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + </intent-filter> + </activity> + <activity android:name=".Unpacker" + android:theme="@android:style/Theme.NoTitleBar.Fullscreen" + android:screenOrientation="landscape" + android:configChanges="orientation|keyboardHidden"> + <meta-data android:name="org.inodes.gus.unpacker.nextActivity" + android:value="org.inodes.gus.scummvm/.ScummVMActivity" /> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> + + <permission android:name="org.inodes.gus.scummvm.permission.SCUMMVM_PLUGIN" + android:label="@string/scummvm_perm_plugin_label" + android:description="@string/scummvm_perm_plugin_desc" + android:protectionLevel="signature" /> + + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + + + <!-- Always needs some sort of qwerty keyboard. + Can work with a D-pad / trackball --> + <uses-configuration android:reqFiveWayNav="true" + android:reqKeyboardType="qwerty"/> + <!-- .. or touchscreen --> + <uses-configuration android:reqTouchScreen="finger" + android:reqKeyboardType="qwerty"/> + <uses-configuration android:reqTouchScreen="stylus" + android:reqKeyboardType="qwerty"/> +</manifest> diff --git a/dists/android/AndroidManifest.xml.in b/dists/android/AndroidManifest.xml.in new file mode 100644 index 0000000000..26a94f957b --- /dev/null +++ b/dists/android/AndroidManifest.xml.in @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="utf-8"?> <!-- -*- xml -*- --> +<!-- NB: android:versionCode needs to be bumped for formal releases --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.inodes.gus.scummvm" + android:versionCode="6" android:versionName="@VERSION@" + android:installLocation="preferExternal"> + + <!-- This version works on Android 1.5 (SDK 3) and newer, but we + want Android 2.2 (SDK 8) defaults and features. + --> + <uses-sdk android:minSdkVersion="3" + android:targetSdkVersion="8" /> + + <application android:name=".ScummVMApplication" + android:label="@string/app_name" + android:description="@string/app_desc" + android:icon="@drawable/scummvm" + android:persistent="true"> + <activity android:name=".ScummVMActivity" + android:theme="@android:style/Theme.NoTitleBar.Fullscreen" + android:screenOrientation="landscape" + android:configChanges="orientation|keyboardHidden" + android:windowSoftInputMode="adjustResize"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + </intent-filter> + </activity> + <activity android:name=".Unpacker" + android:theme="@android:style/Theme.NoTitleBar.Fullscreen" + android:screenOrientation="landscape" + android:configChanges="orientation|keyboardHidden"> + <meta-data android:name="org.inodes.gus.unpacker.nextActivity" + android:value="org.inodes.gus.scummvm/.ScummVMActivity" /> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> + + <permission android:name="org.inodes.gus.scummvm.permission.SCUMMVM_PLUGIN" + android:label="@string/scummvm_perm_plugin_label" + android:description="@string/scummvm_perm_plugin_desc" + android:protectionLevel="signature" /> + + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + + + <!-- Always needs some sort of qwerty keyboard. + Can work with a D-pad / trackball --> + <uses-configuration android:reqFiveWayNav="true" + android:reqKeyboardType="qwerty"/> + <!-- .. or touchscreen --> + <uses-configuration android:reqTouchScreen="finger" + android:reqKeyboardType="qwerty"/> + <uses-configuration android:reqTouchScreen="stylus" + android:reqKeyboardType="qwerty"/> +</manifest> diff --git a/dists/android/mkmanifest.pl b/dists/android/mkmanifest.pl index 00d15f561e..62caa64a55 100644..100755 --- a/dists/android/mkmanifest.pl +++ b/dists/android/mkmanifest.pl @@ -105,6 +105,7 @@ sub print_manifest { 'package' => "org.inodes.gus.scummvm.plugin.$info->{name}", [ANDROID, 'versionCode'] => $package_versionCode, [ANDROID, 'versionName'] => $package_versionName, + [ANDROID, 'installLocation'] => 'preferExternal', ); $writer->startTag( diff --git a/dists/android/res/drawable/scummvm.png b/dists/android/res/drawable/scummvm.png Binary files differnew file mode 100644 index 0000000000..d48cf7f6e8 --- /dev/null +++ b/dists/android/res/drawable/scummvm.png diff --git a/dists/android/res/drawable/scummvm_big.png b/dists/android/res/drawable/scummvm_big.png Binary files differnew file mode 100644 index 0000000000..2c7a8c932d --- /dev/null +++ b/dists/android/res/drawable/scummvm_big.png diff --git a/dists/iphone/Info.plist b/dists/iphone/Info.plist index 9618eb00f3..a042504b9f 100644 --- a/dists/iphone/Info.plist +++ b/dists/iphone/Info.plist @@ -24,6 +24,11 @@ <string>svn</string> <key>CFBundleIconFile</key> <string>icon.png</string> + <key>CFBundleIconFiles</key> + <array> + <string>icon.png</string> + <string>icon-72.png</string> + </array> <key>UIPrerenderedIcon</key> <true/> <key>UIDeviceFamily</key> diff --git a/dists/iphone/icon-72.png b/dists/iphone/icon-72.png Binary files differnew file mode 100644 index 0000000000..d8820f3397 --- /dev/null +++ b/dists/iphone/icon-72.png diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index b149b43ad7..315763a6da 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -208,6 +208,7 @@ static void updateGameDescriptor(GameDescriptor &desc, const ADGameDescription * desc["extra"] = realDesc->extra; desc.setGUIOptions(realDesc->guioptions | params.guioptions); + desc.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(realDesc->language)); } GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const { @@ -305,7 +306,7 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) // If the GUI options were updated, we catch this here and update them in the users config // file transparently. - Common::updateGameGUIOptions(agdDesc->guioptions | params.guioptions); + Common::updateGameGUIOptions(agdDesc->guioptions | params.guioptions, getGameGUIOptionsDescriptionLanguage(agdDesc->language)); debug(2, "Running %s", toGameDescriptor(*agdDesc, params.list).description().c_str()); if (!createInstance(syst, engine, agdDesc)) @@ -340,24 +341,37 @@ static void reportUnknown(const Common::FSNode &path, const SizeMD5Map &filesSiz static ADGameDescList detectGameFilebased(const FileMap &allFiles, const ADParams ¶ms); -static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams ¶ms, Common::Language language, Common::Platform platform, const Common::String &extra) { - FileMap allFiles; - SizeMD5Map filesSizeMD5; - - const ADGameFileDescription *fileDesc; - const ADGameDescription *g; - const byte *descPtr; +static void composeFileHashMap(const Common::FSList &fslist, FileMap &allFiles, int depth, const char **directoryGlobs) { + if (depth <= 0) + return; if (fslist.empty()) - return ADGameDescList(); - Common::FSNode parent = fslist.begin()->getParent(); - debug(3, "Starting detection in dir '%s'", parent.getPath().c_str()); + return; // First we compose a hashmap of all files in fslist. // Includes nifty stuff like removing trailing dots and ignoring case. for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { - if (file->isDirectory()) - continue; + if (file->isDirectory()) { + Common::FSList files; + + if (!directoryGlobs) + continue; + + bool matched = false; + for (const char *glob = *directoryGlobs; *glob; glob++) + if (file->getName().matchString(glob, true)) { + matched = true; + break; + } + + if (!matched) + continue; + + if (!file->getChildren(files, Common::FSNode::kListAll)) + continue; + + composeFileHashMap(files, allFiles, depth - 1, directoryGlobs); + } Common::String tstr = file->getName(); @@ -367,6 +381,24 @@ static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &p allFiles[tstr] = *file; // Record the presence of this file } +} + +static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams ¶ms, Common::Language language, Common::Platform platform, const Common::String &extra) { + FileMap allFiles; + SizeMD5Map filesSizeMD5; + + const ADGameFileDescription *fileDesc; + const ADGameDescription *g; + const byte *descPtr; + + if (fslist.empty()) + return ADGameDescList(); + Common::FSNode parent = fslist.begin()->getParent(); + debug(3, "Starting detection in dir '%s'", parent.getPath().c_str()); + + // First we compose a hashmap of all files in fslist. + // Includes nifty stuff like removing trailing dots and ignoring case. + composeFileHashMap(fslist, allFiles, (params.depth == 0 ? 1 : params.depth), params.directoryGlobs); // Check which files are included in some ADGameDescription *and* present // in fslist. Compute MD5s and file sizes for these files. diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h index 370d958ce6..de4fc3bbf8 100644 --- a/engines/advancedDetector.h +++ b/engines/advancedDetector.h @@ -190,6 +190,21 @@ struct ADParams { * enum for the list. */ uint32 guioptions; + + /** + * Maximum depth of directories to look up + * If set to 0, the depth is 1 level + */ + uint32 depth; + + /** + * Case-insensitive list of directory globs which could be used for + * going deeper int directory structure. + * @see String::matchString() method for format description. + * + * @note Last item must be 0 + */ + const char **directoryGlobs; }; diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index c2c6d10bfe..4a994b731a 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -272,20 +272,19 @@ void AgiEngine::processEvents() { } void AgiEngine::pollTimer() { - static uint32 m = 0; uint32 dm; - if (_tickTimer < m) - m = 0; + if (_tickTimer < _lastTickTimer) + _lastTickTimer = 0; - while ((dm = _tickTimer - m) < 5) { + while ((dm = _tickTimer - _lastTickTimer) < 5) { processEvents(); if (_console->isAttached()) _console->onFrame(); _system->delayMillis(10); _system->updateScreen(); } - m = _tickTimer; + _lastTickTimer = _tickTimer; } void AgiEngine::agiTimerFunctionLow(void *refCon) { @@ -506,13 +505,6 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); - const GameSettings *g; - - const char *gameid = ConfMan.get("gameid").c_str(); - for (g = agiSettings; g->gameid; ++g) - if (!scumm_stricmp(g->gameid, gameid)) - _gameId = g->id; - parseFeatures(); _rnd = new Common::RandomSource(); @@ -543,6 +535,7 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas _allowSynthetic = false; _tickTimer = 0; + _lastTickTimer = 0; _intobj = NULL; @@ -556,7 +549,7 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas _restartGame = false; - _oldMode = -1; + _oldMode = INPUT_NONE; _predictiveDialogRunning = false; _predictiveDictText = NULL; @@ -569,6 +562,10 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas _game.lastController = 0; for (int i = 0; i < MAX_DIRS; i++) _game.controllerOccured[i] = false; + + setupOpcodes(); + _curLogic = NULL; + _timerHack = 0; } void AgiEngine::initialize() { @@ -583,13 +580,19 @@ void AgiEngine::initialize() { } else if (getPlatform() == Common::kPlatformCoCo3) { _soundemu = SOUND_EMU_COCO3; } else { - switch (MidiDriver::detectMusicDriver(MDT_PCSPK)) { - case MD_PCSPK: + switch (MidiDriver::getMusicType(MidiDriver::detectDevice(MDT_PCSPK))) { + case MT_PCSPK: _soundemu = SOUND_EMU_PC; break; - default: + case MT_PCJR: + _soundemu = SOUND_EMU_PCJR; + break; + case MT_ADLIB: _soundemu = SOUND_EMU_NONE; break; + default: + _soundemu = SOUND_EMU_MIDI; + break; } } diff --git a/engines/agi/agi.h b/engines/agi/agi.h index fb9e204101..507e7f7a11 100644 --- a/engines/agi/agi.h +++ b/engines/agi/agi.h @@ -37,6 +37,14 @@ #include "gui/debugger.h" +// AGI resources +#include "agi/console.h" +#include "agi/view.h" +#include "agi/picture.h" +#include "agi/logic.h" +#include "agi/sound.h" + + namespace Common { class RandomSource; } /** @@ -110,23 +118,13 @@ enum AgiGameID { GID_SQ2, GID_XMASCARD, GID_FANMADE, - GID_GETOUTTASQ, + GID_GETOUTTASQ, // Fanmade + GID_SQ0, // Fanmade GID_MICKEY, // PreAGI GID_WINNIE, // PreAGI - GID_TROLL // PreAGI + GID_TROLL // PreAGI }; -} // End of namespace Agi - -// AGI resources -#include "agi/console.h" -#include "agi/view.h" -#include "agi/picture.h" -#include "agi/logic.h" -#include "agi/sound.h" - -namespace Agi { - enum AgiGameType { GType_PreAGI = 0, GType_V2 = 1, @@ -151,7 +149,8 @@ enum AgiGameFeatures { GF_MENUS = (1 << 7), GF_ESCPAUSE = (1 << 8), GF_OLDAMIGAV20 = (1 << 9), - GF_CLIPCOORDS = (1 << 10) + GF_CLIPCOORDS = (1 << 10), + GF_2GSOLDSOUND = (1 << 11) }; struct AGIGameDescription; @@ -316,6 +315,12 @@ enum AgiComputerType { kAgiComputerAmigaOld = 20 // Older Amiga AGI interpreters' value (Seldom used) }; +enum AgiSoundType { + kAgiSoundPC = 1, + kAgiSoundTandy = 3, // Tandy (This value is also used by the Amiga AGI and Apple IIGS AGI) + kAgiSound2GSOld = 8 // Apple IIGS's Gold Rush! (Version 1.0M 1989-02-28 (CE), AGI 3.003) uses value 8 +}; + /** * AGI flags */ @@ -497,10 +502,32 @@ struct ScriptPos { int curIP; }; -#define EGO_VIEW_TABLE 0 -#define HORIZON 36 -#define _WIDTH 160 -#define _HEIGHT 168 +enum { + EGO_VIEW_TABLE = 0, + HORIZON = 36, + _WIDTH = 160, + _HEIGHT = 168 +}; + +enum InputMode { + INPUT_NORMAL = 0x01, + INPUT_GETSTRING = 0x02, + INPUT_MENU = 0x03, + INPUT_NONE = 0x04 +}; + +enum State { + STATE_INIT = 0x00, + STATE_LOADED = 0x01, + STATE_RUNNING = 0x02 +}; + +enum { + SBUF16_OFFSET = 0, + SBUF256_OFFSET = ((_WIDTH) * (_HEIGHT)), + FROM_SBUF16_TO_SBUF256_OFFSET = ((SBUF256_OFFSET) - (SBUF16_OFFSET)), + FROM_SBUF256_TO_SBUF16_OFFSET = ((SBUF16_OFFSET) - (SBUF256_OFFSET)) +}; /** * AGI game structure. @@ -508,10 +535,7 @@ struct ScriptPos { * by the interpreter. */ struct AgiGame { -#define STATE_INIT 0x00 -#define STATE_LOADED 0x01 -#define STATE_RUNNING 0x02 - int state; /**< state of the interpreter */ + State state; /**< state of the interpreter */ // TODO: Check whether adjMouseX and adjMouseY must be saved and loaded when using savegames. // If they must be then loading and saving is partially broken at the moment. @@ -535,12 +559,9 @@ struct AgiGame { uint8 inputBuffer[40]; /**< buffer for user input */ uint8 echoBuffer[40]; /**< buffer for echo.line */ int keypress; -#define INPUT_NORMAL 0x01 -#define INPUT_GETSTRING 0x02 -#define INPUT_MENU 0x03 -#define INPUT_NONE 0x04 - int inputMode; /**< keyboard input mode */ - int inputEnabled; /**< keyboard input enabled */ + + InputMode inputMode; /**< keyboard input mode */ + bool inputEnabled; /**< keyboard input enabled */ int lognum; /**< current logic number */ Common::Array<ScriptPos> execStack; @@ -568,10 +589,7 @@ struct AgiGame { char cursorChar; unsigned int colorFg; unsigned int colorBg; -#define SBUF16_OFFSET 0 -#define SBUF256_OFFSET ((_WIDTH) * (_HEIGHT)) -#define FROM_SBUF16_TO_SBUF256_OFFSET ((SBUF256_OFFSET) - (SBUF16_OFFSET)) -#define FROM_SBUF256_TO_SBUF16_OFFSET ((SBUF16_OFFSET) - (SBUF256_OFFSET)) + uint8 *sbufOrig; /**< Pointer to the 160x336 AGI screen buffer that contains vertically two 160x168 screens (16 color and 256 color). */ uint8 *sbuf16c; /**< 160x168 16 color (+control line & priority information) AGI screen buffer. Points at sbufOrig + SBUF16_OFFSET. */ uint8 *sbuf256c; /**< 160x168 256 color AGI screen buffer (For AGI256 and AGI256-2 support). Points at sbufOrig + SBUF256_OFFSET. */ @@ -774,8 +792,6 @@ public: }; class AgiEngine : public AgiBase { - int _gameId; - protected: // Engine APIs virtual Common::Error go(); @@ -788,9 +804,6 @@ protected: public: AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc); virtual ~AgiEngine(); - int getGameId() { - return _gameId; - } Common::Error loadGameState(int slot); Common::Error saveGameState(int slot, const char *desc); @@ -798,6 +811,7 @@ public: private: uint32 _tickTimer; + uint32 _lastTickTimer; int _keyQueue[KEY_QUEUE_SIZE]; int _keyQueueStart; @@ -829,7 +843,7 @@ public: int loadGameSimple(); uint8 *_intobj; - int _oldMode; + InputMode _oldMode; bool _restartGame; Menu* _menu; @@ -871,7 +885,7 @@ public: static void agiTimerFunctionLow(void *refCon); void initPriTable(); - void newInputMode(int); + void newInputMode(InputMode mode); void oldInputMode(); int getvar(int); @@ -920,6 +934,17 @@ public: int testIfCode(int); void executeAgiCommand(uint8, uint8 *); +private: + // Some submethods of testIfCode + uint8 testObjRight(uint8, uint8, uint8, uint8, uint8); + uint8 testObjCentre(uint8, uint8, uint8, uint8, uint8); + uint8 testObjInBox(uint8, uint8, uint8, uint8, uint8); + uint8 testPosn(uint8, uint8, uint8, uint8, uint8); + uint8 testSaid(uint8, uint8 *); + uint8 testController(uint8); + uint8 testKeypressed(); + uint8 testCompareStrings(uint8, uint8); + // View private: @@ -1024,6 +1049,198 @@ private: bool _predictiveDialogRunning; public: char _predictiveResult[40]; + +private: + typedef void (AgiEngine::*AgiCommand)(uint8 *); + + AgiCommand _agiCommands[183]; + AgiLogic *_curLogic; + int _timerHack; // Workaround for timer loop in MH1 logic 153 + + void setupOpcodes(); + + void cmd_increment(uint8 *p); + void cmd_decrement(uint8 *p); + void cmd_assignn(uint8 *p); + void cmd_assignv(uint8 *p); + void cmd_addn(uint8 *p); + void cmd_addv(uint8 *p); + void cmd_subn(uint8 *p); + void cmd_subv(uint8 *p); // 0x08 + void cmd_lindirectv(uint8 *p); + void cmd_rindirect(uint8 *p); + void cmd_lindirectn(uint8 *p); + void cmd_set(uint8 *p); + void cmd_reset(uint8 *p); + void cmd_toggle(uint8 *p); + void cmd_set_v(uint8 *p); + void cmd_reset_v(uint8 *p); // 0x10 + void cmd_toggle_v(uint8 *p); + void cmd_new_room(uint8 *p); + void cmd_new_room_f(uint8 *p); + void cmd_load_logic(uint8 *p); + void cmd_load_logic_f(uint8 *p); + void cmd_call(uint8 *p); + void cmd_call_f(uint8 *p); + void cmd_load_pic(uint8 *p); // 0x18 + void cmd_draw_pic(uint8 *p); + void cmd_show_pic(uint8 *p); + void cmd_discard_pic(uint8 *p); + void cmd_overlay_pic(uint8 *p); + void cmd_show_pri_screen(uint8 *p); + void cmd_load_view(uint8 *p); + void cmd_load_view_f(uint8 *p); + void cmd_discard_view(uint8 *p); // 0x20 + void cmd_animate_obj(uint8 *p); + void cmd_unanimate_all(uint8 *p); + void cmd_draw(uint8 *p); + void cmd_erase(uint8 *p); + void cmd_position(uint8 *p); + void cmd_position_f(uint8 *p); + void cmd_get_posn(uint8 *p); + void cmd_reposition(uint8 *p); // 0x28 + void cmd_set_view(uint8 *p); + void cmd_set_view_f(uint8 *p); + void cmd_set_loop(uint8 *p); + void cmd_set_loop_f(uint8 *p); + void cmd_fix_loop(uint8 *p); + void cmd_release_loop(uint8 *p); + void cmd_set_cel(uint8 *p); + void cmd_set_cel_f(uint8 *p); // 0x30 + void cmd_last_cel(uint8 *p); + void cmd_current_cel(uint8 *p); + void cmd_current_loop(uint8 *p); + void cmd_current_view(uint8 *p); + void cmd_number_of_loops(uint8 *p); + void cmd_set_priority(uint8 *p); + void cmd_set_priority_f(uint8 *p); + void cmd_release_priority(uint8 *p); // 0x38 + void cmd_get_priority(uint8 *p); + void cmd_stop_update(uint8 *p); + void cmd_start_update(uint8 *p); + void cmd_force_update(uint8 *p); + void cmd_ignore_horizon(uint8 *p); + void cmd_observe_horizon(uint8 *p); + void cmd_set_horizon(uint8 *p); + void cmd_object_on_water(uint8 *p); // 0x40 + void cmd_object_on_land(uint8 *p); + void cmd_object_on_anything(uint8 *p); + void cmd_ignore_objs(uint8 *p); + void cmd_observe_objs(uint8 *p); + void cmd_distance(uint8 *p); + void cmd_stop_cycling(uint8 *p); + void cmd_start_cycling(uint8 *p); + void cmd_normal_cycle(uint8 *p); // 0x48 + void cmd_end_of_loop(uint8 *p); + void cmd_reverse_cycle(uint8 *p); + void cmd_reverse_loop(uint8 *p); + void cmd_cycle_time(uint8 *p); + void cmd_stop_motion(uint8 *p); + void cmd_start_motion(uint8 *p); + void cmd_step_size(uint8 *p); + void cmd_step_time(uint8 *p); // 0x50 + void cmd_move_obj(uint8 *p); + void cmd_move_obj_f(uint8 *p); + void cmd_follow_ego(uint8 *p); + void cmd_wander(uint8 *p); + void cmd_normal_motion(uint8 *p); + void cmd_set_dir(uint8 *p); + void cmd_get_dir(uint8 *p); + void cmd_ignore_blocks(uint8 *p); // 0x58 + void cmd_observe_blocks(uint8 *p); + void cmd_block(uint8 *p); + void cmd_unblock(uint8 *p); + void cmd_get(uint8 *p); + void cmd_get_f(uint8 *p); + void cmd_drop(uint8 *p); + void cmd_put(uint8 *p); + void cmd_put_f(uint8 *p); // 0x60 + void cmd_get_room_f(uint8 *p); + void cmd_load_sound(uint8 *p); + void cmd_sound(uint8 *p); + void cmd_stop_sound(uint8 *p); + void cmd_print(uint8 *p); + void cmd_print_f(uint8 *p); + void cmd_display(uint8 *p); + void cmd_display_f(uint8 *p); // 0x68 + void cmd_clear_lines(uint8 *p); + void cmd_text_screen(uint8 *p); + void cmd_graphics(uint8 *p); + void cmd_set_cursor_char(uint8 *p); + void cmd_set_text_attribute(uint8 *p); + void cmd_shake_screen(uint8 *p); + void cmd_configure_screen(uint8 *p); + void cmd_status_line_on(uint8 *p); // 0x70 + void cmd_status_line_off(uint8 *p); + void cmd_set_string(uint8 *p); + void cmd_get_string(uint8 *p); + void cmd_word_to_string(uint8 *p); + void cmd_parse(uint8 *p); + void cmd_get_num(uint8 *p); + void cmd_prevent_input(uint8 *p); + void cmd_accept_input(uint8 *p); // 0x78 + void cmd_set_key(uint8 *p); + void cmd_add_to_pic(uint8 *p); + void cmd_add_to_pic_f(uint8 *p); + void cmd_status(uint8 *p); + void cmd_save_game(uint8 *p); + void cmd_load_game(uint8 *p); + void cmd_init_disk(uint8 *p); + void cmd_restart_game(uint8 *p); // 0x80 + void cmd_show_obj(uint8 *p); + void cmd_random(uint8 *p); + void cmd_program_control(uint8 *p); + void cmd_player_control(uint8 *p); + void cmd_obj_status_f(uint8 *p); + void cmd_quit(uint8 *p); + void cmd_show_mem(uint8 *p); + void cmd_pause(uint8 *p); // 0x88 + void cmd_echo_line(uint8 *p); + void cmd_cancel_line(uint8 *p); + void cmd_init_joy(uint8 *p); + void cmd_toggle_monitor(uint8 *p); + void cmd_version(uint8 *p); + void cmd_script_size(uint8 *p); + void cmd_set_game_id(uint8 *p); + void cmd_log(uint8 *p); // 0x90 + void cmd_set_scan_start(uint8 *p); + void cmd_reset_scan_start(uint8 *p); + void cmd_reposition_to(uint8 *p); + void cmd_reposition_to_f(uint8 *p); + void cmd_trace_on(uint8 *p); + void cmd_trace_info(uint8 *p); + void cmd_print_at(uint8 *p); + void cmd_print_at_v(uint8 *p); // 0x98 + //void cmd_discard_view(uint8 *p); // Opcode repeated from 0x20 ? + void cmd_clear_text_rect(uint8 *p); + void cmd_set_upper_left(uint8 *p); + void cmd_set_menu(uint8 *p); + void cmd_set_menu_item(uint8 *p); + void cmd_submit_menu(uint8 *p); + void cmd_enable_item(uint8 *p); + void cmd_disable_item(uint8 *p); // 0xa0 + void cmd_menu_input(uint8 *p); + void cmd_show_obj_v(uint8 *p); + void cmd_open_dialogue(uint8 *p); + void cmd_close_dialogue(uint8 *p); + void cmd_mul_n(uint8 *p); + void cmd_mul_v(uint8 *p); + void cmd_div_n(uint8 *p); + void cmd_div_v(uint8 *p); // 0xa8 + void cmd_close_window(uint8 *p); + void cmd_set_simple(uint8 *p); + void cmd_push_script(uint8 *p); + void cmd_pop_script(uint8 *p); + void cmd_hold_key(uint8 *p); + void cmd_set_pri_base(uint8 *p); + void cmd_discard_sound(uint8 *p); + void cmd_hide_mouse(uint8 *p); // 0xb0 + void cmd_allow_menu(uint8 *p); + void cmd_show_mouse(uint8 *p); + void cmd_fence_mouse(uint8 *p); + void cmd_mouse_posn(uint8 *p); + void cmd_release_key(uint8 *p); + void cmd_adj_ego_move_to_x_y(uint8 *p); }; } // End of namespace Agi diff --git a/engines/agi/console.cpp b/engines/agi/console.cpp index a0621f80dd..e881b092e3 100644 --- a/engines/agi/console.cpp +++ b/engines/agi/console.cpp @@ -64,7 +64,7 @@ void Console::postEnter() { bool Console::Cmd_SetVar(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Usage: setvar <varnum> <value>"); + DebugPrintf("Usage: setvar <varnum> <value>\n"); return true; } int p1 = (int)atoi(argv[1]); @@ -76,7 +76,7 @@ bool Console::Cmd_SetVar(int argc, const char **argv) { bool Console::Cmd_SetFlag(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Usage: setvar <varnum> <value>"); + DebugPrintf("Usage: setvar <varnum> <value>\n"); return true; } int p1 = (int)atoi(argv[1]); @@ -88,7 +88,7 @@ bool Console::Cmd_SetFlag(int argc, const char **argv) { bool Console::Cmd_SetObj(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Usage: setvar <varnum> <value>"); + DebugPrintf("Usage: setvar <varnum> <value>\n"); return true; } int p1 = (int)atoi(argv[1]); @@ -99,6 +99,11 @@ bool Console::Cmd_SetObj(int argc, const char **argv) { } bool Console::Cmd_RunOpcode(int argc, const char **argv) { + if (argc < 2) { + DebugPrintf("Usage: runopcode <name> <parameter0> ....\n"); + return true; + } + for (int i = 0; logicNamesCmd[i].name; i++) { if (!strcmp(argv[1], logicNamesCmd[i].name)) { uint8 p[16]; @@ -120,6 +125,8 @@ bool Console::Cmd_RunOpcode(int argc, const char **argv) { } } + DebugPrintf("Unknown opcode\n"); + return true; } @@ -243,6 +250,10 @@ bool Console::Cmd_Cont(int argc, const char **argv) { } bool Console::Cmd_Room(int argc, const char **argv) { + if (argc == 2) { + _vm->newRoom(strtoul(argv[1], NULL, 0)); + } + DebugPrintf("Current room: %d\n", _vm->getvar(0)); return true; diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp index 10df40556f..c185c3efb3 100644 --- a/engines/agi/cycle.cpp +++ b/engines/agi/cycle.cpp @@ -177,9 +177,12 @@ void AgiEngine::updateTimer() { setvar(vDays, getvar(vDays) + 1); } -void AgiEngine::newInputMode(int i) { +void AgiEngine::newInputMode(InputMode mode) { + if (mode == INPUT_MENU && !getflag(fMenusWork) && !(getFeatures() & GF_MENUS)) + return; + _oldMode = _game.inputMode; - _game.inputMode = i; + _game.inputMode = mode; } void AgiEngine::oldInputMode() { @@ -314,7 +317,8 @@ int AgiEngine::playGame() { _game.clockEnabled = true; _game.lineUserInput = 22; - if (getFeatures() & GF_AGIMOUSE) + // We run AGIMOUSE always as a side effect + if (getFeatures() & GF_AGIMOUSE || 1) report("Using AGI Mouse 1.0 protocol\n"); if (getFeatures() & GF_AGIPAL) @@ -386,28 +390,33 @@ int AgiEngine::runGame() { _restartGame = false; } - // Set computer type (v20 i.e. vComputer) + // Set computer type (v20 i.e. vComputer) and sound type switch (getPlatform()) { case Common::kPlatformAtariST: setvar(vComputer, kAgiComputerAtariST); + setvar(vSoundgen, kAgiSoundPC); break; case Common::kPlatformAmiga: if (getFeatures() & GF_OLDAMIGAV20) setvar(vComputer, kAgiComputerAmigaOld); else setvar(vComputer, kAgiComputerAmiga); + setvar(vSoundgen, kAgiSoundTandy); break; case Common::kPlatformApple2GS: setvar(vComputer, kAgiComputerApple2GS); + if (getFeatures() & GF_2GSOLDSOUND) + setvar(vSoundgen, kAgiSound2GSOld); + else + setvar(vSoundgen, kAgiSoundTandy); break; case Common::kPlatformPC: default: setvar(vComputer, kAgiComputerPC); + setvar(vSoundgen, kAgiSoundPC); break; } - setvar(vSoundgen, 1); // IBM PC SOUND - // Set monitor type (v26 i.e. vMonitor) switch (_renderMode) { case Common::kRenderCGA: @@ -430,7 +439,7 @@ int AgiEngine::runGame() { setvar(vFreePages, 180); // Set amount of free memory to realistic value setvar(vMaxInputChars, 38); _game.inputMode = INPUT_NONE; - _game.inputEnabled = 0; + _game.inputEnabled = false; _game.hasPrompt = 0; _game.state = STATE_RUNNING; diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp index e72647d5e2..d1bed5d716 100644 --- a/engines/agi/detection.cpp +++ b/engines/agi/detection.cpp @@ -125,841 +125,7 @@ static const PlainGameDescriptor agiGames[] = { {0, 0} }; - -namespace Agi { - -using Common::GUIO_NONE; - -#define GAME_LVFPN(id,name,fname,md5,size,lang,ver,features,gid,platform,interp) { \ - { \ - id, \ - name, \ - AD_ENTRY1s(fname,md5,size), \ - lang, \ - platform, \ - ADGF_NO_FLAGS, \ - GUIO_NONE \ - }, \ - gid, \ - interp, \ - features, \ - ver, \ - } - -#define GAME_LVFPNF(id,name,fname,md5,size,lang,ver,features,gid,platform,interp) { \ - { \ - id, \ - name, \ - AD_ENTRY1s(fname,md5,size), \ - lang, \ - platform, \ - ADGF_USEEXTRAASTITLE, \ - GUIO_NONE \ - }, \ - gid, \ - interp, \ - features, \ - ver, \ - } - -#define GAME(id,name,md5,ver,gid) GAME_LVFPN(id,name,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V2) -#define GAME3(id,name,fname,md5,ver,gid) GAME_LVFPN(id,name,fname,md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V3) - -#define GAME_P(id,name,md5,ver,gid,platform) GAME_LVFPN(id,name,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_V2) - -#define GAME_FP(id,name,md5,ver,flags,gid,platform) GAME_LVFPN(id,name,"logdir",md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V2) - -#define GAME_PS(id,name,md5,size,ver,gid,platform) GAME_LVFPN(id,name,"logdir",md5,size,Common::EN_ANY,ver,0,gid,platform,GType_V2) - -#define GAME_LPS(id,name,md5,size,lang,ver,gid,platform) GAME_LVFPN(id,name,"logdir",md5,size,lang,ver,0,gid,platform,GType_V2) - -#define GAME_LFPS(id,name,md5,size,lang,ver,flags,gid,platform) GAME_LVFPN(id,name,"logdir",md5,size,lang,ver,flags,gid,platform,GType_V2) - -#define GAME3_P(id,name,fname,md5,ver,flags,gid,platform) GAME_LVFPN(id,name,fname,md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V3) - -#define GAMEpre_P(id,name,fname,md5,ver,gid,platform) GAME_LVFPN(id,name,fname,md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI) - -#define GAMEpre_PS(id,name,fname,md5,size,ver,gid,platform) GAME_LVFPN(id,name,fname,md5,size,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI) - -#define GAME3_PS(id,name,fname,md5,size,ver,flags,gid,platform) GAME_LVFPN(id,name,fname,md5,size,Common::EN_ANY,ver,flags,gid,platform,GType_V3) - -#define FANMADE_ILVF(id,name,md5,lang,ver,features) GAME_LVFPNF(id,name,"logdir",md5,-1,lang,ver,(GF_FANMADE|features),GID_FANMADE,Common::kPlatformPC,GType_V2) - -#define FANMADE_ISVP(id,name,md5,size,ver,platform) GAME_LVFPNF(id,name,"logdir",md5,size,Common::EN_ANY,ver,GF_FANMADE,GID_FANMADE,platform,GType_V2) -#define FANMADE_SVP(name,md5,size,ver,platform) FANMADE_ISVP("agi-fanmade",name,md5,size,ver,platform) - -#define FANMADE_LVF(name,md5,lang,ver,features) FANMADE_ILVF("agi-fanmade",name,md5,lang,ver,features) - -#define FANMADE_LF(name,md5,lang,features) FANMADE_LVF(name,md5,lang,0x2917,features) -#define FANMADE_IF(id,name,md5,features) FANMADE_ILVF(id,name,md5,Common::EN_ANY,0x2917,features) - -#define FANMADE_V(name,md5,ver) FANMADE_LVF(name,md5,Common::EN_ANY,ver,0) -#define FANMADE_F(name,md5,features) FANMADE_LF(name,md5,Common::EN_ANY,features) -#define FANMADE_L(name,md5,lang) FANMADE_LF(name,md5,lang,0) -#define FANMADE_I(id,name,md5) FANMADE_IF(id,name,md5,0) - -#define FANMADE(name,md5) FANMADE_F(name,md5,0) - -static const AGIGameDescription gameDescriptions[] = { - - // AGI Demo 1 (PC) 05/87 [AGI 2.425] - GAME("agidemo", "Demo 1 1987-05-20", "9c4a5b09cc3564bc48b4766e679ea332", 0x2440, GID_AGIDEMO), - - // AGI Demo 2 (IIgs) 1.0C (Censored) - GAME_P("agidemo", "Demo 2 1987-11-24 1.0C", "580ffdc569ff158f56fb92761604f70e", 0x2917, GID_AGIDEMO, Common::kPlatformApple2GS), - - // AGI Demo 2 (PC 3.5") 11/87 [AGI 2.915] - GAME("agidemo", "Demo 2 1987-11-24 3.5\"", "e8ebeb0bbe978172fe166f91f51598c7", 0x2917, GID_AGIDEMO), - - // AGI Demo 2 (PC 5.25") 11/87 [v1] [AGI 2.915] - GAME("agidemo", "Demo 2 1987-11-24 [version 1] 5.25\"", "852ac303a374df62571642ca1e2d1f0a", 0x2917, GID_AGIDEMO), - - // AGI Demo 2 (PC 5.25") 01/88 [v2] [AGI 2.917] - GAME("agidemo", "Demo 2 1987-11-25 [version 2] 5.25\"", "1503f02086ea9f388e7e041c039eaa69", 0x2917, GID_AGIDEMO), - - // AGI Demo 3 (PC) 09/88 [AGI 3.002.102] - GAME3("agidemo", "Demo 3 1988-09-13", "dmdir", "289c7a2c881f1d973661e961ced77d74", 0x3149, GID_AGIDEMO), - - // AGI Demo for Kings Quest III and Space Quest I - GAME("agidemo", "Demo Kings Quest III and Space Quest I", "502e6bf96827b6c4d3e67c9cdccd1033", 0x2272, GID_AGIDEMO), - - // Black Cauldron (Amiga) 2.00 6/14/87 - GAME_P("bc", "2.00 1987-06-14", "7b01694af21213b4727bb94476f64eb5", 0x2440, GID_BC, Common::kPlatformAmiga), - - // Black Cauldron (Apple IIgs) 1.0O 2/24/89 (CE) - // Menus not tested - GAME3_P("bc", "1.0O 1989-02-24 (CE)", "bcdir", "dc09d30b147242692f4f85b9811962db", 0x3149, 0, GID_BC, Common::kPlatformApple2GS), - - // Black Cauldron (PC) 2.00 6/14/87 [AGI 2.439] - GAME("bc", "2.00 1987-06-14", "7f598d4712319b09d7bd5b3be10a2e4a", 0x2440, GID_BC), - - // Black Cauldron (Russian) - GAME_LPS("bc", "", "b7de782dfdf8ea7dde8064f09804bcf5", 357, Common::RU_RUS, 0x2440, GID_BC, Common::kPlatformPC), - - // Black Cauldron (PC 5.25") 2.10 11/10/88 [AGI 3.002.098] - GAME3("bc", "2.10 1988-11-10 5.25\"", "bcdir", "0c5a9acbcc7e51127c34818e75806df6", 0x3149, GID_BC), - - // Black Cauldron (PC) 2.10 [AGI 3.002.097] - GAME3("bc", "2.10", "bcdir", "0de3953c9225009dc91e5b0d1692967b", 0x3149, GID_BC), - - // Black Cauldron (CoCo3 360k) [AGI 2.023] - GAME_PS("bc", "", "51212c54808ade96176f201ae0ac7a6f", 357, 0x2440, GID_BC, Common::kPlatformCoCo3), - - // Black Cauldron (CoCo3 360k) [AGI 2.072] - GAME_PS("bc", "updated", "c4e1937f74e8100cd0152b904434d8b4", 357, 0x2440, GID_BC, Common::kPlatformCoCo3), - -// TODO -// These aren't supposed to work now as they require unsupported agi engine 2.01 -#if 0 - // Donald Duck's Playground (Amiga) 1.0C - // Menus not tested - GAME_P("ddp", "1.0C 1987-04-27", "550971d196f65190a5c760d2479406ef", 0x2272, GID_DDP, Common::kPlatformAmiga), - - // Donald Duck's Playground (ST) 1.0A 8/8/86 - // Menus not tested - GAME("ddp", "1.0A 1986-08-08", "64388812e25dbd75f7af1103bc348596", 0x2272, GID_DDP), - - // reported by Filippos (thebluegr) in bugreport #1654500 - // Menus not tested - GAME_PS("ddp", "1.0C 1986-06-09", "550971d196f65190a5c760d2479406ef", 132, 0x2272, GID_DDP, Common::kPlatformPC), -#endif - - // Gold Rush! (Amiga) 1.01 1/13/89 aka 2.05 3/9/89 # 2.316 - GAME3_PS("goldrush", "1.01 1989-01-13 aka 2.05 1989-03-09", "dirs", "a1d4de3e75c2688c1e2ca2634ffc3bd8", 2399, 0x3149, 0, GID_GOLDRUSH, Common::kPlatformAmiga), - - // Gold Rush! (Apple IIgs) 1.0M 2/28/89 (CE) aka 2.01 12/22/88 - // Menus not tested - GAME3_P("goldrush", "1.0M 1989-02-28 (CE) aka 2.01 1988-12-22", "grdir", "3f7b9ce62631434389f85371b11921d6", 0x3149, 0, GID_GOLDRUSH, Common::kPlatformApple2GS), - - // Gold Rush! (ST) 1.01 1/13/89 aka 2.01 12/22/88 - GAME3_P("goldrush", "1.01 1989-01-13 aka 2.01 1988-12-22", "grdir", "4dd4d50480a3d6c206fa227ce8142735", 0x3149, 0, GID_GOLDRUSH, Common::kPlatformAtariST), - - // Gold Rush! (PC 5.25") 2.01 12/22/88 [AGI 3.002.149] - GAME3("goldrush", "2.01 1988-12-22 5.25\"", "grdir", "db733d199238d4009a9e95f11ece34e9", 0x3149, GID_GOLDRUSH), - - // Gold Rush! (PC 3.5") 2.01 12/22/88 [AGI 3.002.149] - GAME3("goldrush", "2.01 1988-12-22 3.5\"", "grdir", "6a285235745f69b4b421403659497216", 0x3149, GID_GOLDRUSH), - - // Gold Rush! (PC 3.5", bought from The Software Farm) 3.0 1998-12-22 [AGI 3.002.149] - GAME3("goldrush", "3.0 1998-12-22 3.5\"", "grdir", "6882b6090473209da4cd78bb59f78dbe", 0x3149, GID_GOLDRUSH), - - { - // Gold Rush! (PC 5.25") 2.01 12/22/88 [AGI 3.002.149] - { - "goldrush", - "2.01 1988-12-22", - { - { "grdir", 0, "db733d199238d4009a9e95f11ece34e9", 2399}, - { "vol.0", 0, "4b6423d143674d3757ab1b875d25951d", 25070}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_GOLDRUSH, - GType_V3, - GF_MACGOLDRUSH, - 0x3149, - }, - - - // Gold Rush! (CoCo3 720k) [AGI 2.023] - GAME_PS("goldrush", "", "0a41b65efc0cd6c4271e957e6ffbbd8e", 744, 0x2440, GID_GOLDRUSH, Common::kPlatformCoCo3), - - // Gold Rush! (CoCo3 360k/720k) [AGI 2.072] - GAME_PS("goldrush", "updated", "c49bf56bf91e31a4601a604e51ef8bfb", 744, 0x2440, GID_GOLDRUSH, Common::kPlatformCoCo3), - - // King's Quest 1 (Amiga) 1.0U # 2.082 - // The original game did not have menus, they are enabled under ScummVM - GAME_FP("kq1", "1.0U 1986", "246c695324f1c514aee2b904fa352fad", 0x2440, GF_MENUS, GID_KQ1, Common::kPlatformAmiga), - - // King's Quest 1 (ST) 1.0V - // The original game did not have menus, they are enabled under ScummVM - GAME_FP("kq1", "1.0V 1986", "c3a017e556c4b0eece366a4cd9abb657", 0x2272, GF_MENUS, GID_KQ1, Common::kPlatformAtariST), - - // King's Quest 1 (IIgs) 1.0S-88223 - // Menus not tested - GAME_P("kq1", "1.0S 1988-02-23", "f4277aa34b43d37382bc424c81627617", 0x2272, GID_KQ1, Common::kPlatformApple2GS), - - // King's Quest 1 (Mac) 2.0C - GAME_P("kq1", "2.0C 1987-03-26", "d4c4739d4ac63f7dbd29255425077d48", 0x2440, GID_KQ1, Common::kPlatformMacintosh), - - // King's Quest 1 (PC 5.25"/3.5") 2.0F [AGI 2.917] - GAME("kq1", "2.0F 1987-05-05 5.25\"/3.5\"", "10ad66e2ecbd66951534a50aedcd0128", 0x2917, GID_KQ1), - - // King's Quest 1 (CoCo3 360k) [AGI 2.023] - GAME_PS("kq1", "", "10ad66e2ecbd66951534a50aedcd0128", 315, 0x2440, GID_KQ1, Common::kPlatformCoCo3), - - // King's Quest 1 (CoCo3 360k) [AGI 2.023] - GAME_PS("kq1", "fixed", "4c8ef8b5d2f1b6c1a93e456d1f1ffc74", 768, 0x2440, GID_KQ1, Common::kPlatformCoCo3), - - // King's Quest 1 (CoCo3 360k) [AGI 2.072] - GAME_PS("kq1", "updated", "94087178c78933a4af3cd24d1c8dd7b2", 315, 0x2440, GID_KQ1, Common::kPlatformCoCo3), - - // King's Quest 2 (IIgs) 2.0A 6/16/88 (CE) - GAME_P("kq2", "2.0A 1988-06-16 (CE)", "5203c8b95250a2ecfee93ddb99414753", 0x2917, GID_KQ2, Common::kPlatformApple2GS), - - // King's Quest 2 (Amiga) 2.0J (Broken) - GAME_P("kq2", "2.0J 1987-01-29 [OBJECT decrypted]", "b866f0fab2fad91433a637a828cfa410", 0x2440, GID_KQ2, Common::kPlatformAmiga), - - // King's Quest 2 (Mac) 2.0R - GAME_P("kq2", "2.0R 1988-03-23", "cbdb0083317c8e7cfb7ac35da4bc7fdc", 0x2440, GID_KQ2, Common::kPlatformMacintosh), - - // King's Quest 2 (PC) 2.1 [AGI 2.411]; entry from DAGII, but missing from Sarien? - // XXX: any major differences from 2.411 to 2.440? - GAME("kq2", "2.1 1987-04-10", "759e39f891a0e1d86dd29d7de485c6ac", 0x2440, GID_KQ2), - - // King's Quest 2 (PC 5.25"/3.5") 2.2 [AGI 2.426] - GAME("kq2", "2.2 1987-05-07 5.25\"/3.5\"", "b944c4ff18fb8867362dc21cc688a283", 0x2917, GID_KQ2), - - // King's Quest 2 (Russian) - GAME_LPS("kq2", "", "35211c574ececebdc723b23e35f99275", 543, Common::RU_RUS, 0x2917, GID_KQ2, Common::kPlatformPC), - - // King's Quest 2 (CoCo3 360k) [AGI 2.023] - GAME_PS("kq2", "", "b944c4ff18fb8867362dc21cc688a283", 543, 0x2440, GID_KQ2, Common::kPlatformCoCo3), - - // King's Quest 2 (CoCo3 360k) [AGI 2.072] - GAME_PS("kq2", "updated", "f64a606de740a5348f3d125c03e989fe", 543, 0x2440, GID_KQ2, Common::kPlatformCoCo3), - - // King's Quest 2 (CoCo3 360k) [AGI 2.023] - GAME_PS("kq2", "fixed", "fb33ac2768a94a89117a270771db465c", 768, 0x2440, GID_KQ2, Common::kPlatformCoCo3), - - // King's Quest 3 (Amiga) 1.01 11/8/86 - // The original game did not have menus, they are enabled under ScummVM - GAME_FP("kq3", "1.01 1986-11-08", "8ab343306df0e2d98f136be4e8cfd0ef", 0x2440, GF_MENUS, GID_KQ3, Common::kPlatformAmiga), - - // King's Quest 3 (ST) 1.02 11/18/86 - // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game - GAME_FP("kq3", "1.02 1986-11-18", "8846df2654302b623217ba8bd6d657a9", 0x2272, GF_ESCPAUSE, GID_KQ3, Common::kPlatformAtariST), - - // King's Quest 3 (Mac) 2.14 3/15/88 - GAME_P("kq3", "2.14 1988-03-15", "7639c0da5ce94848227d409351fabda2", 0x2440, GID_KQ3, Common::kPlatformMacintosh), - - // King's Quest 3 (IIgs) 2.0A 8/28/88 (CE) - GAME_P("kq3", "2.0A 1988-08-28 (CE)", "ac30b7ca5a089b5e642fbcdcbe872c12", 0x2917, GID_KQ3, Common::kPlatformApple2GS), - - // King's Quest 3 (Amiga) 2.15 11/15/89 # 2.333 - // Original pauses with ESC, has menus accessible with mouse. - // ver = 0x3086 -> menus accessible with ESC or mouse, bug #2835581 (KQ3: Game Crash When Leaving Tavern as Fly). - // ver = 0x3149 -> menus accessible with mouse, ESC pauses game, bug #2835581 disappears. - GAME3_PS("kq3", "2.15 1989-11-15", "dirs", "8e35bded2bc5cf20f5eec2b15523b155", 1805, 0x3149, 0, GID_KQ3, Common::kPlatformAmiga), - - // King's Quest 3 (PC) 1.01 11/08/86 [AGI 2.272] - // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game - GAME_FP("kq3", "1.01 1986-11-08", "9c2b34e7ffaa89c8e2ecfeb3695d444b", 0x2272, GF_ESCPAUSE, GID_KQ3, Common::kPlatformPC), - - // King's Quest 3 (Russian) - GAME_LFPS("kq3", "", "5856dec6ccb9c4b70aee21044a19270a", 390, Common::RU_RUS, 0x2272, GF_ESCPAUSE, GID_KQ3, Common::kPlatformPC), - - // King's Quest 3 (PC 5.25") 2.00 5/25/87 [AGI 2.435] - GAME("kq3", "2.00 1987-05-25 5.25\"", "18aad8f7acaaff760720c5c6885b6bab", 0x2440, GID_KQ3), - - // King's Quest 3 (Mac) 2.14 3/15/88 - // Menus not tested - GAME_P("kq3", "2.14 1988-03-15 5.25\"", "7650e659c7bc0f1e9f8a410b7a2e9de6", 0x2440, GID_KQ3, Common::kPlatformMacintosh), - - // King's Quest 3 (PC 3.5") 2.14 3/15/88 [AGI 2.936] - GAME("kq3", "2.14 1988-03-15 3.5\"", "d3d17b77b3b3cd13246749231d9473cd", 0x2936, GID_KQ3), - - // King's Quest 3 (CoCo3 158k/360k) [AGI 2.023] - GAME_PS("kq3", "", "5a6be7d16b1c742c369ef5cc64fefdd2", 429, 0x2440, GID_KQ3, Common::kPlatformCoCo3), - - // King's Quest 4 (PC 5.25") 2.0 7/27/88 [AGI 3.002.086] - GAME3("kq4", "2.0 1988-07-27", "kq4dir", "f50f7f997208ca0e35b2650baec43a2d", 0x3086, GID_KQ4), - - // King's Quest 4 (PC 3.5") 2.0 7/27/88 [AGI 3.002.086] - GAME3("kq4", "2.0 1988-07-27 3.5\"", "kq4dir", "fe44655c42f16c6f81046fdf169b6337", 0x3086, GID_KQ4), - - // King's Quest 4 (PC 3.5") 2.2 9/27/88 [AGI 3.002.086] - // Menus not tested - GAME3("kq4", "2.2 1988-09-27 3.5\"", "kq4dir", "7470b3aeb49d867541fc66cc8454fb7d", 0x3086, GID_KQ4), - - // King's Quest 4 (PC 5.25") 2.3 9/27/88 [AGI 3.002.086] - GAME3("kq4", "2.3 1988-09-27", "kq4dir", "6d7714b8b61466a5f5981242b993498f", 0x3086, GID_KQ4), - - // King's Quest 4 (PC 3.5") 2.3 9/27/88 [AGI 3.002.086] - GAME3("kq4", "2.3 1988-09-27 3.5\"", "kq4dir", "82a0d39af891042e99ac1bd6e0b29046", 0x3086, GID_KQ4), - - // King's Quest 4 (IIgs) 1.0K 11/22/88 (CE) - // Menus not tested - GAME3_P("kq4", "1.0K 1988-11-22", "kq4dir", "8536859331159f15012e35dc82cb154e", 0x3086, 0, GID_KQ4, Common::kPlatformApple2GS), - - // King's Quest 4 demo (PC) [AGI 3.002.102] - // Menus not tested - GAME3("kq4", "Demo 1988-12-20", "dmdir", "a3332d70170a878469d870b14863d0bf", 0x3149, GID_KQ4), - - // King's Quest 4 (CoCo3 720k) [AGI 2.023] - GAME_PS("kq4", "", "9e7729a28e749ca241d2bf71b9b2dbde", 741, 0x2440, GID_KQ4, Common::kPlatformCoCo3), - - // King's Quest 4 (CoCo3 360k/720k) [AGI 2.072] - GAME_PS("kq4", "updated", "1959ca10739edb34069bb504dbd74805", 741, 0x2440, GID_KQ4, Common::kPlatformCoCo3), - - // Leisure Suit Larry 1 (PC 5.25"/3.5") 1.00 6/1/87 [AGI 2.440] - GAME("lsl1", "1.00 1987-06-01 5.25\"/3.5\"", "1fe764e66857e7f305a5f03ca3f4971d", 0x2440, GID_LSL1), - - // Leisure Suit Larry 1 Polish - GAME_LPS("lsl1", "2.00 2001-12-11", "7ba1fccc46d27c141e704706c1d0a85f", 303, Common::PL_POL, 0x2440, GID_LSL1, Common::kPlatformPC), - - // Leisure Suit Larry 1 Polish - Demo - GAME_LPS("lsl1", "Demo", "3b2f564306c401dff6334441df967ddd", 666, Common::PL_POL, 0x2917, GID_LSL1, Common::kPlatformPC), - - // Leisure Suit Larry 1 (ST) 1.04 6/18/87 - GAME_P("lsl1", "1.04 1987-06-18", "8b579f8673fe9448c2538f5ed9887cf0", 0x2440, GID_LSL1, Common::kPlatformAtariST), - - // Leisure Suit Larry 1 (Amiga) 1.05 6/26/87 # x.yyy - GAME_P("lsl1", "1.05 1987-06-26", "3f5d26d8834ca49c147fb60936869d56", 0x2440, GID_LSL1, Common::kPlatformAmiga), - - // Leisure Suit Larry 1 (IIgs) 1.0E - GAME_P("lsl1", "1.0E 1987", "5f9e1dd68d626c6d303131c119582ad4", 0x2440, GID_LSL1, Common::kPlatformApple2GS), - - // Leisure Suit Larry 1 (Mac) 1.05 6/26/87 - GAME_P("lsl1", "1.05 1987-06-26", "8a0076429890531832f0dc113285e31e", 0x2440, GID_LSL1, Common::kPlatformMacintosh), - - // Leisure Suit Larry 1 (CoCo3 158k/360k) [AGI 2.072] - GAME_PS("lsl1", "", "a2de1fe76565c3e8b40c9d036b5e5612", 198, 0x2440, GID_LSL1, Common::kPlatformCoCo3), - - // Manhunter NY (ST) 1.03 10/20/88 - GAME3_P("mh1", "1.03 1988-10-20", "mhdir", "f2d58056ad802452d60776ee920a52a6", 0x3149, 0, GID_MH1, Common::kPlatformAtariST), - - // Manhunter NY (IIgs) 2.0E 10/05/88 (CE) - GAME3_P("mh1", "2.0E 1988-10-05 (CE)", "mhdir", "2f1509f76f24e6e7d213f2dadebbf156", 0x3149, 0, GID_MH1, Common::kPlatformApple2GS), - - // Manhunter NY (Amiga) 1.06 3/18/89 - GAME3_P("mh1", "1.06 1989-03-18", "dirs", "92c6183042d1c2bb76236236a7d7a847", 0x3149, GF_OLDAMIGAV20, GID_MH1, Common::kPlatformAmiga), - - // reported by Filippos (thebluegr) in bugreport #1654500 - // Manhunter NY (PC 5.25") 1.22 8/31/88 [AGI 3.002.107] - GAME3_PS("mh1", "1.22 1988-08-31", "mhdir", "0c7b86f05fe02c2e26cff1b07450b82a", 2123, 0x3149, 0, GID_MH1, Common::kPlatformPC), - - // Manhunter NY (PC 3.5") 1.22 8/31/88 [AGI 3.002.102] - GAME3_PS("mh1", "1.22 1988-08-31", "mhdir", "5b625329021ad49fd0c1d6f2d6f54bba", 2141, 0x3149, 0, GID_MH1, Common::kPlatformPC), - - // Manhunter NY (CoCo3 720k) [AGI 2.023] - GAME_PS("mh1", "", "b968285caf2f591c78dd9c9e26ab8974", 495, 0x2440, GID_MH1, Common::kPlatformCoCo3), - - // Manhunter NY (CoCo3 360k/720k) [AGI 2.072] - GAME_PS("mh1", "updated", "d47da950c62289f8d4ccf36af73365f2", 495, 0x2440, GID_MH1, Common::kPlatformCoCo3), - - // Manhunter SF (ST) 1.0 7/29/89 - GAME3_P("mh2", "1.0 1989-07-29", "mh2dir", "5e3581495708b952fea24438a6c7e040", 0x3149, 0, GID_MH1, Common::kPlatformAtariST), - - // Manhunter SF (Amiga) 3.06 8/17/89 # 2.333 - GAME3_PS("mh2", "3.06 1989-08-17", "dirs", "b412e8a126368b76696696f7632d4c16", 2573, 0x3086, GF_OLDAMIGAV20, GID_MH2, Common::kPlatformAmiga), - - // Manhunter SF (PC 5.25") 3.03 8/17/89 [AGI 3.002.149] - GAME3("mh2", "3.03 1989-08-17 5.25\"", "mh2dir", "b90e4795413c43de469a715fb3c1fa93", 0x3149, GID_MH2), - - // Manhunter SF (PC 3.5") 3.02 7/26/89 [AGI 3.002.149] - GAME3("mh2", "3.02 1989-07-26 3.5\"", "mh2dir", "6fb6f0ee2437704c409cf17e081ba152", 0x3149, GID_MH2), - - // Manhunter SF (CoCo3 720k) [AGI 2.023] - GAME_PS("mh2", "", "acaaa577e10d1753c5a74f6ae1d858d4", 591, 0x2440, GID_MH2, Common::kPlatformCoCo3), - - // Manhunter SF (CoCo3 720k) [AGI 2.072] - GAME_PS("mh2", "updated", "c64875766700196e72a92359f70f45a9", 591, 0x2440, GID_MH2, Common::kPlatformCoCo3), - - // Mickey's Space Adventure - // Preagi game - GAMEpre_P("mickey", "", "1.pic", "b6ec04c91a05df374792872c4d4ce66d", 0x0000, GID_MICKEY, Common::kPlatformPC), - -#if 0 - // Mixed-Up Mother Goose (Amiga) 1.1 - // Problematic: crashes - // Menus not tested - GAME3_PS("mixedup", "1.1 1986-12-10", "dirs", "5c1295fe6daaf95831195ba12894dbd9", 2021, 0x3086, 0, GID_MIXEDUP, Common::kPlatformAmiga), -#endif - - // Mixed Up Mother Goose (IIgs) - GAME_P("mixedup", "1987", "3541954a7303467c6df87665312ffb6a", 0x2917, GID_MIXEDUP, Common::kPlatformApple2GS), - - // Mixed-Up Mother Goose (PC) [AGI 2.915] - GAME("mixedup", "1987-11-10", "e524655abf9b96a3b179ffcd1d0f79af", 0x2917, GID_MIXEDUP), - - // Mixed-Up Mother Goose (CoCo3 360k) [AGI 2.072] - GAME_PS("mixedup", "", "44e63e9b4d4822a31edea0e8a7e7eac4", 606, 0x2440, GID_MIXEDUP, Common::kPlatformCoCo3), - - // Police Quest 1 (PC) 2.0E 11/17/87 [AGI 2.915] - GAME("pq1", "2.0E 1987-11-17", "2fd992a92df6ab0461d5a2cd83c72139", 0x2917, GID_PQ1), - - // Police Quest 1 (Mac) 2.0G 12/3/87 - GAME_P("pq1", "2.0G 1987-12-03", "805750b66c1c5b88a214e67bfdca17a1", 0x2440, GID_PQ1, Common::kPlatformMacintosh), - - // Police Quest 1 (IIgs) 2.0B-88421 - GAME_P("pq1", "2.0B 1988-04-21", "e7c175918372336461e3811d594f482f", 0x2917, GID_PQ1, Common::kPlatformApple2GS), - - // Police Quest 1 (Amiga) 2.0B 2/22/89 # 2.310 - GAME3_PS("pq1", "2.0B 1989-02-22", "dirs", "cfa93e5f2aa7378bddd10ad6746a2ffb", 1613, 0x3149, 0, GID_PQ1, Common::kPlatformAmiga), - - // Police Quest 1 (IIgs) 2.0A-88318 - GAME_P("pq1", "2.0A 1988-03-18", "8994e39d0901de3d07cecfb954075bb5", 0x2917, GID_PQ1, Common::kPlatformApple2GS), - - // Police Quest 1 (PC) 2.0A 10/23/87 [AGI 2.903/2.911] - GAME("pq1", "2.0A 1987-10-23", "b9dbb305092851da5e34d6a9f00240b1", 0x2917, GID_PQ1), - - // Police Quest 1 (Russian) - GAME_LPS("pq1", "", "604cc8041d24c4c7e5fa8baf386ef76e", 360, Common::RU_RUS, 0x2917, GID_PQ1, Common::kPlatformPC), - - // Police Quest 1 2.0G 12/3/87 - GAME("pq1", "2.0G 1987-12-03 5.25\"/ST", "231f3e28170d6e982fc0ced4c98c5c1c", 0x2440, GID_PQ1), - - // Police Quest 1 (PC) 2.0G 12/3/87; entry from DAGII, but missing from Sarien? - // not sure about disk format -- dsymonds - GAME("pq1", "2.0G 1987-12-03", "d194e5d88363095f55d5096b8e32fbbb", 0x2917, GID_PQ1), - - // Police Quest 1 (CoCo3 360k) [AGI 2.023] - GAME_PS("pq1", "", "28a077041f75aab78f66804800940085", 375, 0x2440, GID_PQ1, Common::kPlatformCoCo3), - - // Police Quest 1 (CoCo3 360k) [AGI 2.072] - GAME_PS("pq1", "updated", "63b9a9c6eec154751dd446cd3693e0e2", 768, 0x2440, GID_PQ1, Common::kPlatformCoCo3), - - // Space Quest 1 (ST) 1.1A - // The original game did not have menus, they are enabled under ScummVM - GAME_FP("sq1", "1.1A 1986-02-06", "6421fb64b0e6604c9dd065975d9279e9", 0x2440, GF_MENUS, GID_SQ1, Common::kPlatformAtariST), - - // Space Quest 1 (PC 360k) 1.1A [AGI 2.272] - // The original game did not have menus, they are enabled under ScummVM - GAME_FP("sq1", "1.1A 1986-11-13", "8d8c20ab9f4b6e4817698637174a1cb6", 0x2272, GF_MENUS, GID_SQ1, Common::kPlatformPC), - - // Space Quest 1 (PC 720k) 1.1A [AGI 2.272] - // The original game did not have menus, they are enabled under ScummVM - GAME_FP("sq1", "1.1A 720kb", "0a92b1be7daf3bb98caad3f849868aeb", 0x2272, GF_MENUS, GID_SQ1, Common::kPlatformPC), - - // Space Quest 1 (Amiga) 1.2 # 2.082 - // The original game did not have menus, they are enabled under ScummVM - GAME_FP("sq1", "1.2 1986", "0b216d931e95750f1f4837d6a4b821e5", 0x2440, GF_MENUS | GF_OLDAMIGAV20, GID_SQ1, Common::kPlatformAmiga), - - // Space Quest 1 (Mac) 1.5D - GAME_P("sq1", "1.5D 1987-04-02", "ce88419aadd073d1c6682d859b3d8aa2", 0x2440, GID_SQ1, Common::kPlatformMacintosh), - - // Space Quest 1 (IIgs) 2.2 - GAME_P("sq1", "2.2 1987", "64b9b3d04c1066d36e6a6e56187a83f7", 0x2917, GID_SQ1, Common::kPlatformApple2GS), - - // Space Quest 1 (PC) 1.0X [AGI 2.089] - // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game - GAME_FP("sq1", "1.0X 1986-09-24", "af93941b6c51460790a9efa0e8cb7122", 0x2089, GF_ESCPAUSE, GID_SQ1, Common::kPlatformPC), - - // Space Quest 1 (Russian) - GAME_LFPS("sq1", "", "a279eb8ddbdefdb1ea6adc827a1d632a", 372, Common::RU_RUS, 0x2089, GF_ESCPAUSE, GID_SQ1, Common::kPlatformPC), - - // Space Quest 1 (PC 5.25"/3.5") 2.2 [AGI 2.426/2.917] - GAME("sq1", "2.2 1987-05-07 5.25\"/3.5\"", "5d67630aba008ec5f7f9a6d0a00582f4", 0x2440, GID_SQ1), - - // Space Quest 1 (CoCo3 360k) [AGI 2.072] - GAME_PS("sq1", "", "5d67630aba008ec5f7f9a6d0a00582f4", 372, 0x2440, GID_SQ1, Common::kPlatformCoCo3), - - // Space Quest 1 (CoCo3 360k) [AGI 2.023] - GAME_PS("sq1", "fixed", "ca822b768b6462e410423ea7f498daee", 768, 0x2440, GID_SQ1, Common::kPlatformCoCo3), - - // Space Quest 1 (CoCo3 360k) [AGI 2.072] - GAME_PS("sq1", "updated", "7fa54e6bb7ffeb4cf20eca39d86f5fb2", 387, 0x2440, GID_SQ1, Common::kPlatformCoCo3), - - // Space Quest 2 (PC 3.5") 2.0D [AGI 2.936] - GAME("sq2", "2.0D 1988-03-14 3.5\"", "85390bde8958c39830e1adbe9fff87f3", 0x2936, GID_SQ2), - - // Space Quest 2 (IIgs) 2.0A 7/25/88 (CE) - GAME_P("sq2", "2.0A 1988-07-25 (CE)", "5dfdac98dd3c01fcfb166529f917e911", 0x2936, GID_SQ2, Common::kPlatformApple2GS), - - { - // Space Quest 2 (Amiga) 2.0F - { - "sq2", - "2.0F 1986-12-09 [VOL.2->PICTURE.16 broken]", - { - { "logdir", 0, "28add5125484302d213911df60d2aded", 426}, - { "object", 0, "5dc52be721257719f4b311a84ce22b16", 372}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_SQ2, - GType_V2, - 0, - 0x2936, - }, - - - // Space Quest 2 (Mac) 2.0D - GAME_P("sq2", "2.0D 1988-04-04", "bfbebe0b59d83f931f2e1c62ce9484a7", 0x2936, GID_SQ2, Common::kPlatformMacintosh), - - // reported by Filippos (thebluegr) in bugreport #1654500 - // Space Quest 2 (PC 5.25") 2.0A [AGI 2.912] - GAME_PS("sq2", "2.0A 1987-11-06 5.25\"", "ad7ce8f800581ecc536f3e8021d7a74d", 423, 0x2917, GID_SQ2, Common::kPlatformPC), - - // Space Quest 2 (Russian) - GAME_LPS("sq2", "", "ba21c8934caf28e3ba45ce7d1cd6b041", 423, Common::RU_RUS, 0x2917, GID_SQ2, Common::kPlatformPC), - - // Space Quest 2 (PC 3.5") 2.0A [AGI 2.912] - GAME_PS("sq2", "2.0A 1987-11-06 3.5\"", "6c25e33d23b8bed42a5c7fa63d588e5c", 423, 0x2917, GID_SQ2, Common::kPlatformPC), - - // Space Quest 2 (PC 5.25"/ST) 2.0C/A [AGI 2.915] - // Menus not tested - GAME("sq2", "2.0C/A 5.25\"/ST", "bd71fe54869e86945041700f1804a651", 0x2917, GID_SQ2), - - // Space Quest 2 (PC 3.5") 2.0F [AGI 2.936] - GAME("sq2", "2.0F 1989-01-05 3.5\"", "28add5125484302d213911df60d2aded", 0x2936, GID_SQ2), - - // Space Quest 2 (CoCo3 360k) [AGI 2.023] - GAME_PS("sq2", "", "12973d39b892dc9d280257fd271e9597", 768, 0x2440, GID_SQ2, Common::kPlatformCoCo3), - - // Space Quest 2 (CoCo3 360k) [AGI 2.072] - GAME_PS("sq2", "updated", "d24f19b047e65e1763eff4b46f3d50df", 768, 0x2440, GID_SQ2, Common::kPlatformCoCo3), - - // Troll's Tale - GAMEpre_PS("troll", "", "troll.img", "62903f264b3d849be4214b3a5c42a2fa", 184320, 0x0000, GID_TROLL, Common::kPlatformPC), - - // Winnie the Pooh in the Hundred Acre Wood - GAMEpre_P("winnie", "", "title.pic", "2e7900c1ccaa7671d65405f6d1efed30", 0x0000, GID_WINNIE, Common::kPlatformPC), - - // Winnie the Pooh in the Hundred Acre Wood (Amiga) - GAMEpre_P("winnie", "", "title", "2e7900c1ccaa7671d65405f6d1efed30", 0x0000, GID_WINNIE, Common::kPlatformAmiga), - - // Winnie the Pooh in the Hundred Acre Wood (C64) - GAMEpre_P("winnie", "", "title.pic", "d4eb97cffc866110f71e1ec9f84fe643", 0x0000, GID_WINNIE, Common::kPlatformC64), - - // Winnie the Pooh in the Hundred Acre Wood (Apple //gs) - GAMEpre_P("winnie", "", "title.pic", "45e06010a3c61d78f4661103c901ae11", 0x0000, GID_WINNIE, Common::kPlatformApple2GS), - - // Xmas Card 1986 (PC) [AGI 2.272] - GAME("xmascard", "1986-11-13 [version 1]", "3067b8d5957e2861e069c3c0011bd43d", 0x2272, GID_XMASCARD), - - // Xmas Card 1986 (CoCo3 360k) [AGI 2.072] - GAME_PS("xmascard", "", "25ad35e9628fc77e5e0dd35852a272b6", 768, 0x2440, GID_XMASCARD, Common::kPlatformCoCo3), - - FANMADE_F("2 Player Demo", "4279f46b3cebd855132496476b1d2cca", GF_AGIMOUSE), - FANMADE("AGI Contest 1 Template", "d879aed25da6fc655564b29567358ae2"), - FANMADE("AGI Contest 2 Template", "5a2fb2894207eff36c72f5c1b08bcc07"), - FANMADE("AGI Mouse Demo 0.60 demo 1", "c07e2519de674c67386cb2cc6f2e3904"), - FANMADE("AGI Mouse Demo 0.60 demo 2", "cc49d8b88ed6faf4f53ce92c84e0fe1b"), - FANMADE("AGI Mouse Demo 0.70", "3497c291e4afb6f758e61740678a2aec"), - FANMADE_F("AGI Mouse Demo 1.00", "20397f0bf0ef936f416bb321fb768fc7", GF_AGIMOUSE), - FANMADE_F("AGI Mouse Demo 1.10", "f4ad396b496d6167635ad0b410312ab8", GF_AGIMOUSE|GF_AGIPAL), - FANMADE("AGI Piano (v1.0)", "8778b3d89eb93c1d50a70ef06ef10310"), - FANMADE("AGI Quest (v1.46-TJ0)", "1cf1a5307c1a0a405f5039354f679814"), - FANMADE_I("tetris", "", "7a874e2db2162e7a4ce31c9130248d8a"), - FANMADE_V("AGI Trek (Demo)", "c02882b8a8245b629c91caf7eb78eafe", 0x2440), - FANMADE_F("AGI256 Demo", "79261ac143b2e2773b2753674733b0d5", GF_AGI256), - FANMADE_F("AGI256-2 Demo", "3cad9b3aff1467cebf0c5c5b110985c5", GF_AGI256_2), - FANMADE_LF("Abrah: L'orphelin de l'espace (v1.2)", "b7b6d1539e14d5a26fa3088288e1badc", Common::FR_FRA, GF_AGIPAL), - FANMADE("Acidopolis", "7017db1a4b726d0d59e65e9020f7d9f7"), - FANMADE("Agent 0055 (v1.0)", "c2b34a0c77acb05482781dda32895f24"), - FANMADE("Agent 06 vs. The Super Nazi", "136f89ca9f117c617e88a85119777529"), - FANMADE("Agent Quest", "59e49e8f72058a33c00d60ee1097e631"), - FANMADE("Al Pond - On Holiday (v1.0)", "a84975496b42d485920e886e92eed68b"), - FANMADE("Al Pond - On Holiday (v1.1)", "7c95ac4689d0c3bfec61e935f3093634"), - FANMADE("Al Pond - On Holiday (v1.3)", "8f30c260de9e1dd3d8b8f89cc19d2633"), - FANMADE("Al Pond 1 - Al Lives Forever (v1.0)", "e8921c3043b749b056ff51f56d1b451b"), - FANMADE("Al Pond 1 - Al Lives Forever (v1.3)", "fb4699474054962e0dbfb4cf12ca52f6"), - FANMADE("Apocalyptic Quest (v0.03 Teaser)", "42ced528b67965d3bc3b52c635f94a57"), - FANMADE_F("Apocalyptic Quest (v4.00 Alpha 1)", "e15581628d84949b8d352d224ec3184b", GF_AGIMOUSE), - FANMADE_F("Apocalyptic Quest (v4.00 Alpha 2)", "0eee850005860e46345b38fea093d194", GF_AGIMOUSE), - FANMADE_F("Band Quest (Demo)", "7326abefd793571cc17ed0db647bdf34", GF_AGIMOUSE), - FANMADE_F("Band Quest (Early Demo)", "de4758dd34676b248c8301b32d93bc6f", GF_AGIMOUSE), - FANMADE("Beyond the Titanic 2", "9b8de38dc64ffb3f52b7877ea3ebcef9"), - FANMADE("Biri Quest 1", "1b08f34f2c43e626c775c9d6649e2f17"), - FANMADE("Bob The Farmboy", "e4b7df9d0830addee5af946d380e66d7"), - FANMADE_F("Boring Man 1: The Toad to Robinland", "d74481cbd227f67ace37ce6a5493039f", GF_AGIMOUSE), - FANMADE_F("Boring Man 2: Ho Man! This Game Sucks!", "250032ba105bdf7c1bc4fed767c2d37e", GF_AGIMOUSE), - FANMADE("Botz", "a8fabe4e807adfe5ec02bfec6d983695"), - FANMADE("Brian's Quest (v1.0)", "0964aa79b9cdcff7f33a12b1d7e04b9c"), - FANMADE("CPU-21 (v1.0)", "35b7cdb4d17e890e4c52018d96e9cbf4"), - FANMADE_I("caitlyn", "Demo", "5b8a3cdb2fc05469f8119d49f50fbe98"), - FANMADE_I("caitlyn", "", "818469c484cae6dad6f0e9a353f68bf8"), - FANMADE("Car Driver (v1.1)", "2311611d2d36d20ccc9da806e6cba157"), - FANMADE("Cloak of Darkness (v1.0)", "5ba6e18bf0b53be10db8f2f3831ee3e5"), - FANMADE("Coco Coq (English) - Coco Coq In Grostesteing's Base (v.1.0.3)", "97631f8e710544a58bd6da9e780f9320"), - FANMADE_L("Coco Coq (French) - Coco Coq Dans la Base de Grostesteing (v1.0.2)", "ef579ebccfe5e356f9a557eb3b2d8649", Common::FR_FRA), - FANMADE("Corby's Murder Mystery (v1.0)", "4ebe62ac24c5a8c7b7898c8eb070efe5"), - FANMADE_F("DG: The AGIMouse Adventure (English v1.1)", "efe453b92bc1487ea69fbebede4d5f26", GF_AGIMOUSE|GF_AGIPAL), - FANMADE_LF("DG: The AGIMouse Adventure (French v1.1)", "eb3d17ca466d672cbb95947e8d6e846a", Common::FR_FRA, GF_AGIMOUSE|GF_AGIPAL), - FANMADE("DG: The Adventure Game (English v1.1)", "0d6376d493fa7a21ec4da1a063e12b25"), - FANMADE_L("DG: The Adventure Game (French v1.1)", "258bdb3bb8e61c92b71f2f456cc69e23", Common::FR_FRA), - FANMADE("Dashiki (16 Colors)", "9b2c7b9b0283ab9f12bedc0cb6770a07"), - FANMADE_F("Dashiki (256 Colors)", "c68052bb209e23b39b55ff3d759958e6", GF_AGIMOUSE|GF_AGI256), - FANMADE("Date Quest 1 (v1.0)", "ba3dcb2600645be53a13170aa1a12e69"), - FANMADE("Date Quest 2 (v1.0 Demo)", "1602d6a2874856e928d9a8c8d2d166e9"), - FANMADE("Date Quest 2 (v1.0)", "f13f6fc85aa3e6e02b0c20408fb63b47"), - FANMADE("Dave's Quest (v0.07)", "f29c3660de37bacc1d23547a167f27c9"), - FANMADE("Dave's Quest (v0.17)", "da3772624cc4a86f7137db812f6d7c39"), - FANMADE("Disco Nights (Demo)", "dc5a2b21182ba38bdcd992a3a978e690"), - FANMADE("Dogs Quest - The Quest for the Golden Bone (v1.0)", "f197357edaaea0ff70880602d2f09b3e"), - FANMADE("Dr. Jummybummy's Space Adventure", "988bd81785f8a452440a2a8ac67f96aa"), - FANMADE("Ed Ward", "98be839b9f30cbedea4c9cee5442d827"), - FANMADE("Elfintard", "c3b847e9e9e978af9708df76a0751dc2"), - FANMADE("Enclosure (v1.01)", "f08e66fee9ecdde77db7ee9a10c96ba2"), - FANMADE("Enclosure (v1.03)", "e4a0613ed02401502e506ba3565a8c40"), - FANMADE_SVP("Enclosure", "fe98e6126db74c6cc6fd8fe395cc6e8c", 345, 0x2440, Common::kPlatformCoCo3), - FANMADE("Epic Fighting (v0.1)", "aff24a1b3bdd676187685c4d95ba4294"), - FANMADE("Escape Quest (v0.0.3)", "2346b65619b1da0298b715b06d1a45a1"), - FANMADE("Escape from the Desert (beta 1)", "dfdc634d340854bd6ece28024010758d"), - FANMADE("Escape from the Salesman", "e723ca4fe0f6f56affe039fbb4dbeb6c"), - FANMADE("Fu$k Quest 1 (final)", "1cd0587422313f6ca77d6a95988e88ed"), - FANMADE("Fu$k Quest 1", "1cd0587422313f6ca77d6a95988e88ed"), - FANMADE("Fu$k Quest 2 - Romancing the Bone (Teaser)", "d288355d71d9bb1639260ccaa3b2fbfe"), - FANMADE("Fu$k Quest 2 - Romancing the Bone", "294beeb7765c7ea6b05ed7b9bf7bff4f"), - FANMADE("Gennadi Tahab Autot - Mission Pack 1 - Kuressaare", "bfa5fe71978e6ccf3d4eedd430124015"), - FANMADE("Go West, Young Hippie", "ff31484ea465441cb5f3a0f8e956b716"), - FANMADE("Good Man (demo v3.41)", "3facd8a8f856b7b6e0f6c3200274d88c"), - - { - // Groza - { - "agi-fanmade", - "Groza (russian) [AGDS sample]", - AD_ENTRY1("logdir", "421da3a18004122a966d64ab6bd86d2e"), - Common::RU_RUS, - Common::kPlatformPC, - ADGF_USEEXTRAASTITLE, - GUIO_NONE - }, - GID_FANMADE, - GType_V2, - GF_AGDS, - 0x2440, - }, - - { - // Get Outta SQ - { - "agi-fanmade", - "Get Outta Space Quest", - AD_ENTRY1("logdir", "aaea5b4a348acb669d13b0e6f22d4dc9"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_USEEXTRAASTITLE, - GUIO_NONE - }, - GID_GETOUTTASQ, - GType_V2, - 0, - 0x2440, - }, - - FANMADE_F("Half-Death - Terror At White-Mesa", "b62c05d0ace878261392073f57ae788c", GF_AGIMOUSE), - FANMADE("Hank's Quest (v1.0 English) - Victim of Society", "64c15b3d0483d17888129100dc5af213"), - FANMADE("Hank's Quest (v1.1 English) - Victim of Society", "86d1f1dd9b0c4858d096e2a60cca8a14"), - FANMADE_L("Hank's Quest (v1.81 Dutch) - Slachtoffer Van Het Gebeuren", "41e53972d55ff3dff9e90d15fe1b659f", Common::NL_NLD), - FANMADE("Hank's Quest (v1.81 English) - Victim of Society", "7a776383282f62a57c3a960dafca62d1"), - FANMADE("Herbao (v0.2)", "6a5186fc8383a9060517403e85214fc2"), - FANMADE_F("Hitler's Legacy (v.0004q)", "a412881269ba34584bd0a3268e5a9863", GF_AGIMOUSE), - FANMADE("Hobbits", "4a1c1ef3a7901baf0ab45fde0cfadd89"), - FANMADE_F("Isabella Coq - A Present For My Dad", "55c6819f2330c4d5d6459874c9f123d9", GF_AGIMOUSE), - FANMADE("Jack & Julia - VAMPYR", "8aa0b9a26f8d5a4421067ab8cc3706f6"), - FANMADE("Jeff's Quest (v.5 alpha Jun 1)", "10f1720eed40c12b02a0f32df3e72ded"), - FANMADE("Jeff's Quest (v.5 alpha May 31)", "51ff71c0ed90db4e987a488ed3bf0551"), - FANMADE("Jen's Quest (Demo 1)", "361afb5bdb6160213a1857245e711939"), - FANMADE("Jen's Quest (Demo 2)", "3c321eee33013b289ab8775449df7df2"), - FANMADE("Jiggy Jiggy Uh! Uh!", "bc331588a71e7a1c8840f6cc9b9487e4"), - FANMADE("Jimmy In: The Alien Attack (v0.1)", "a4e9db0564a494728de7873684a4307c"), - FANMADE("Joe McMuffin In \"What's Cooking, Doc\" (v1.0)", "8a3de7e61a99cb605fa6d233dd91c8e1"), - FANMADE_LVF("Jolimie, le Village Maudit (v0.5)", "21818501636b3cb8ad5de5c1a66de5c2", Common::FR_FRA, 0x2936, GF_AGIMOUSE|GF_AGIPAL), - FANMADE_LVF("Jolimie, le Village Maudit (v1.1)", "68d7aef1161bb5972fe03efdf29ccb7f", Common::FR_FRA, 0x2936, GF_AGIMOUSE|GF_AGIPAL), - FANMADE("Journey Of Chef", "aa0a0b5a6364801ae65fdb96d6741df5"), - FANMADE("Jukebox (v1.0)", "c4b9c5528cc67f6ba777033830de7751"), - FANMADE("Justin Quest (v1.0 in development)", "103050989da7e0ffdc1c5e1793a4e1ec"), - FANMADE("J\xf5ulumaa (v0.05) (Estonian)", "53982ecbfb907e41392b3961ad1c3475"), - FANMADE("Kings Quest 2 - Breast Intentions (v2.0 Mar 26)", "a25d7379d281b1b296d4785df90a8e78"), - FANMADE("Kings Quest 2 - Breast Intentions (v2.0 Aug 16)", "6b4f796d0421d2e12e501b511962e03a"), - FANMADE("Lasse Holm: The Quest for Revenge (v1.0)", "f9fbcc8a4ef510bfbb92423296ff4abb"), - FANMADE("Lawman for Hire", "c78b28bfd3767dd455b992cd8b7854fa"), - FANMADE("Lefty Goes on Vacation (Not in The Right Place)", "ccdc49a33870310b01f2c48b8a1f3c34"), - FANMADE("Les Ins\xe3parables (v1.0)", "4b780887cab0ecabc5eca319acb3acf2"), - FANMADE("Little Pirate (Demo 2 v0.6)", "437068efe4ec32d436da09d6f2ea56e1"), - FANMADE("Lost Eternity (v1.0)", "95f15c5632feb8a39e9ca3d9af35fcc9"), - FANMADE("MD Quest - The Search for Michiel (v0.10)", "2a6fcb21d2b5e4144c38ed817fabe8ee"), - FANMADE("Maale Adummin Quest", "ddfbeb33feb7cf78504fe4dba14ec63b"), - FANMADE("Monkey Man", "2322d03f997e8cc235d4578efff69cfa"), - FANMADE_F("Napalm Quest (v0.5)", "b659afb491d967bb34810d1c6ce22093", GF_AGIMOUSE), - FANMADE("Naturette 1 (English v1.2)", "0a75884e7f010974a230bdf269651117"), - FANMADE("Naturette 1 (English v1.3)", "f15bbf999ac55ebd404aa1eb84f7c1d9"), - FANMADE_L("Naturette 1 (French v1.2)", "d3665622cc41aeb9c7ecf4fa43f20e53", Common::FR_FRA), - FANMADE_F("Naturette 2: Daughter of the Moon (v1.0)", "bdf76a45621c7f56d1c9d40292c6137a", GF_AGIMOUSE|GF_AGIPAL), - FANMADE_F("Naturette 3: Adventure in Treeworld (v1.0a)", "6dbb0e7fc75fec442e6d9e5a06f1530e", GF_AGIMOUSE|GF_AGIPAL), - FANMADE_F("Naturette 4: From a Planet to Another Planet (Not Finished)", "13be8cd9cf35aeff0a39b8757057fbc8", GF_AGIMOUSE), - // FIXME: Actually Naturette 4 has both English and French language support built into it. How to add that information? - FANMADE_F("Naturette 4: From a Planet to Another Planet (2007-10-05)", "8253706b6ef5423a79413b216760297c", GF_AGIMOUSE|GF_AGIPAL), - FANMADE("New AGI Hangman Test", "d69c0e9050ccc29fd662b74d9fc73a15"), - FANMADE("Nick's Quest - In Pursuit of QuakeMovie (v2.1 Gold)", "e29cbf9222551aee40397fabc83eeca0"), - FANMADE_F("Open Mic Night (v0.1)", "70000a2f67aac27d1133d019df70246d", GF_AGIMOUSE|GF_AGIPAL), - FANMADE("Operation: Recon", "0679ce8405411866ccffc8a6743370d0"), - FANMADE("Patrick's Quest (Demo v1.0)", "f254f5b894b98fec5f92acc07fb62841"), - FANMADE("Phantasmagoria", "87d20c1c11aee99a4baad3797b63146b"), - FANMADE("Pharaoh Quest (v0.0)", "51c630899d076cf799e573dadaa2276d"), - FANMADE("Phil's Quest - the Search for Tolbaga", "5e7ca45c360e03164b8358e49900c588"), - FANMADE("Pinkun Maze Quest (v0.1)", "148ff0843af389928b3939f463bfd20d"), - FANMADE("Pirate Quest", "bb612a919ed2b9ea23bbf03ce69fed42"), - FANMADE("Pothead (v0.1)", "d181101385d3a45082f418cd4b3c5b01"), - FANMADE("President's Quest", "4937d0e8ecadb7888faeb347799b0388"), - FANMADE("Prince Quest", "266248d75c3130c8ccc9c9bf2ad30a0d"), - FANMADE("Professor (English) - The Professor is Missing (Mar 17)", "6232de31cc204affdf2e92dfe3dc0e4d"), - FANMADE("Professor (English) - The Professor is Missing (Mar 22)", "b5fcf0ca2f0d1c073be82f01e2170961"), - FANMADE_L("Professor (French) - Le Professeur a Disparu", "7d9f8a4d4610bb9b0b97caa17590c2d3", Common::FR_FRA), - FANMADE("Quest for Glory VI - Hero's Adventure", "d26765c3075064c80d284c5e06e33a7e"), - FANMADE("Quest for Home", "d2895dc1cd3930f2489af0f843b144b3"), - FANMADE("Quest for Ladies (demo v1.1 Apr 1)", "3f6e02f16e1154a0daf296c8895edd97"), - FANMADE("Quest for Ladies (demo v1.1 Apr 6)", "f75e7b6a0769a3fa926eea0854711591"), - FANMADE("Quest for Piracy 1 - Enter the Silver Pirate (v0.15)", "d23f5c2a26f6dc60c686f8a2436ea4a6"), - FANMADE("Quest for a Record Deal", "f4fbd7abf056d2d3204f790da5ac89ab"), - FANMADE("Ralph's Quest (v0.1)", "5cf56378aa01a26ec30f25295f0750ca"), - FANMADE("Residence 44 Quest (Dutch v0.99)", "7c5cc64200660c70240053b33d379d7d"), - FANMADE("Residence 44 Quest (English v0.99)", "fe507851fddc863d540f2bec67cc67fd"), - FANMADE("Residence 44 Quest (English v1.0a)", "f99e3f69dc8c77a45399da9472ef5801"), - FANMADE("SQ2Eye (v0.3)", "2be2519401d38ad9ce8f43b948d093a3"), - // FANMADE("SQ2Eye (v0.4)", "2be2519401d38ad9ce8f43b948d093a3"), - FANMADE("SQ2Eye (v0.41)", "f0e82c55f10eb3542d7cd96c107ae113"), - FANMADE("SQ2Eye (v0.42)", "d7beae55f6328ef8b2da47b1aafea40c"), - FANMADE("SQ2Eye (v0.43)", "2a895f06e45de153bb4b77c982009e06"), - FANMADE("SQ2Eye (v0.44)", "5174fc4b6d8a477ba0ff0575cd64e0aa"), - FANMADE("SQ2Eye (v0.45)", "6e06f8bb7b90ce6f6aabf1a0e620159c"), - FANMADE("SQ2Eye (v0.46)", "bf0ad7a035ff9113951d09d1efe380c4"), - FANMADE("SQ2Eye (v0.47)", "85dc3be1d33ff932c292b74f9037abaa"), - FANMADE("SQ2Eye (v0.48)", "587574252972a5b5c070a647973a9b4a"), - FANMADE("SQ2Eye (v0.481)", "fc9234beb49804ae869696ce5af8ef30"), - FANMADE("SQ2Eye (v0.482)", "3ed84b7b87fa6840f25c15f250a11ffb"), - FANMADE("SQ2Eye (v0.483)", "647c31298d3f9cda641231b893e347c0"), - FANMADE("SQ2Eye (v0.484)", "f2c86fae7b9046d408c62c8c49a4b882"), - FANMADE("SQ2Eye (v0.485)", "af59e36bc28f44545458b68a93e91e67"), - FANMADE("SQ2Eye (v0.486)", "3fd86436e93456770dbdd4593eded70a"), - FANMADE("Save Santa (v1.0)", "4644f6beb5802081772f14be56ae196c"), - FANMADE("Save Santa (v1.3)", "f8afdb6efc5af5e7c0228b44633066af"), - FANMADE("Schiller (preview 1)", "ade39dea968c959cfebe1cf935d653e9"), - FANMADE("Schiller (preview 2)", "62cd1f8fc758bf6b4aa334e553624cef"), - FANMADE_IF("serguei1", "v1.0", "b86725f067e456e10cdbdf5f58e01dec", GF_AGIMOUSE|GF_AGIPAL), - FANMADE_IF("serguei1", "v1.1 2002 Sep 5", "91975c1fb4b13b0f9a8e9ff74731030d", GF_AGIMOUSE|GF_AGIPAL), - FANMADE_IF("serguei1", "v1.1 2003 Apr 10", "91975c1fb4b13b0f9a8e9ff74731030d", GF_AGIMOUSE|GF_AGIPAL), - FANMADE_IF("serguei2", "v0.1.1 Demo", "906ccbc2ddedb29b63141acc6d10cd28", GF_AGIMOUSE), - FANMADE_IF("serguei2", "v1.3.1 Demo (March 22nd 2008)", "ad1308fcb8f48723cd388e012ebf5e20", GF_AGIMOUSE|GF_AGIPAL), - FANMADE("Shifty (v1.0)", "2a07984d27b938364bf6bd243ac75080"), - FANMADE_F("Sliding Tile Game (v1.00)", "949bfff5d8a81c3139152eed4d84ca75", GF_AGIMOUSE), - FANMADE("Snowboarding Demo (v1.0)", "24bb8f29f1eddb5c0a099705267c86e4"), - FANMADE("Solar System Tour", "b5a3d0f392dfd76a6aa63f3d5f578403"), - FANMADE("Sorceror's Appraisal", "fe62615557b3cb7b08dd60c9d35efef1"), - FANMADE_I("sq0", "v1.03", "d2fd6f7404e86182458494e64375e590"), - FANMADE_I("sq0", "v1.04", "2ad9d1a4624a98571ee77dcc83f231b6"), - FANMADE_ISVP("sq0", "", "e1a8e4efcce86e1efcaa14633b9eb986", 762, 0x2440, Common::kPlatformCoCo3), - FANMADE_I("sqx", "v10.0 Feb 05", "c992ae2f8ab18360404efdf16fa9edd1"), - FANMADE_I("sqx", "v10.0 Jul 18", "812edec45cefad559d190ffde2f9c910"), - FANMADE_ISVP("sqx", "", "f0a59044475a5fa37c055d8c3eb4d1a7", 768, 0x2440, Common::kPlatformCoCo3), - FANMADE_F("Space Quest 3.5", "c077bc28d7b36213dd99dc9ecb0147fc", GF_AGIMOUSE|GF_AGIPAL), - FANMADE_F("Space Trek (v1.0)", "807a1aeadb2ace6968831d36ab5ea37a", GF_CLIPCOORDS), - FANMADE("Special Delivery", "88764dfe61126b8e73612c851b510a33"), - FANMADE("Speeder Bike Challenge (v1.0)", "2deb25bab379285ca955df398d96c1e7"), - FANMADE("Star Commander 1 - The Escape (v1.0)", "a7806f01e6fa14ebc029faa58f263750"), - FANMADE("Star Pilot: Bigger Fish", "8cb26f8e1c045b75c6576c839d4a0172"), - FANMADE_F("Street Quest (Demo)", "cf2aa94a7eb78dce6892c37f03e310d6", GF_AGIPAL), - FANMADE("Tales of the Tiki", "8103c9c87e3964690a14a3d0d83f7ddc"), - FANMADE("Tex McPhilip 1 - Quest For The Papacy", "3c74b9a24b51aa8020ac82bee3132266"), - FANMADE("Tex McPhilip 2 - Road To Divinity (v1.5)", "7387e8df854440bc26620ca0ea43af9a"), - FANMADE("Tex McPhilip 3 - A Destiny of Sin (Demo v0.25)", "992d12031a486ad84e592ff5d7c9d782"), - FANMADE("The 13th Disciple (v1.00)", "887719ad59afce9a41ec057dbb73ad73"), - FANMADE("The Adventures of a Crazed Hermit", "6e3086cbb794d3299a9c5a9792295511"), - FANMADE("The Grateful Dead", "c2146631afacf8cb455ce24f3d2d46e7"), - FANMADE("The Legend of Shay-Larah 1 - The Lost Prince", "04e720c8e30c9cf12db22ea14a24a3dd"), - FANMADE("The Legend of Zelda: The Fungus of Time (Demo v1.00)", "dcaf8166ceb62a3d9b9aea7f3b197c09"), - FANMADE("The Legendary Harry Soupsmith (Demo 1998 Apr 2)", "64c46b0d6fc135c9835afa80980d2831"), - FANMADE("The Legendary Harry Soupsmith (Demo 1998 Aug 19)", "8d06d82970f2c591d880a95476efbcf0"), - FANMADE("The Long Haired Dude: Encounter of the 18-th Kind", "86ea17b9fc2f3e537a7e40863d352c29"), - FANMADE("The Lost Planet (v0.9)", "590dffcbd932a9fbe554be13b769cac0"), - FANMADE("The Lost Planet (v1.0)", "58564df8b6394612dd4b6f5c0fd68d44"), - FANMADE("The New Adventure of Roger Wilco (v1.00)", "e5f0a7cb8d49f66b89114951888ca688"), - FANMADE("The Ruby Cast (v0.02)", "ed138e461bb1516e097007e017ab62df"), - FANMADE("The Shadow Plan", "c02cd10267e721f4e836b1431f504a0a"), - FANMADE("Time Quest (Demo v0.1)", "12e1a6f03ea4b8c5531acd0400b4ed8d"), - FANMADE("Time Quest (Demo v0.2)", "7b710608abc99e0861ac59b967bf3f6d"), - FANMADE_SVP("Time Quest", "90314f473d8317be5cd1f0306f139aea", 300, 0x2440, Common::kPlatformCoCo3), - FANMADE("Tonight The Shrieking Corpses Bleed (Demo v0.11)", "bcc57a7c8d563fa0c333107ae1c0a6e6"), - FANMADE("Tonight The Shrieking Corpses Bleed (v1.01)", "36b38f621b38e8d104aa0807302dc8c9"), - FANMADE("Turks' Quest - Heir to the Planet", "3d19254b737c8b218e5bc4580542b79a"), - FANMADE("URI Quest (v0.173 Feb 27)", "3986eefcf546dafc45f920ae91a697c3"), - FANMADE("URI Quest (v0.173 Jan 29)", "494150940d34130605a4f2e67ee40b12"), - { - // V - The Graphical Adventure - { - "agi-fanmade", - "V - The Graphical Adventure (Demo 2)", - AD_ENTRY1s("vdir", "c71f5c1e008d352ae9040b77fcf79327", 3080), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_USEEXTRAASTITLE, - GUIO_NONE - }, - GID_FANMADE, - GType_V3, - GF_FANMADE, - 0x3149, - }, - FANMADE_SVP("V - The Graphical Adventure", "1646eaade74f137a9041eb427a389969", 768, 0x2440, Common::kPlatformCoCo3), - - FANMADE("Voodoo Girl - Queen of the Darned (v1.2 2002 Jan 1)", "ae95f0c77d9a97b61420fd192348b937"), - FANMADE("Voodoo Girl - Queen of the Darned (v1.2 2002 Mar 29)", "11d0417b7b886f963d0b36789dac4c8f"), - FANMADE("Wizaro (v0.1)", "abeec1eda6eaf8dbc52443ea97ff140c"), - - { AD_TABLE_END_MARKER, 0, 0, 0, 0 } -}; - -/** - * The fallback game descriptor used by the AGI engine's fallbackDetector. - * Contents of this struct are to be overwritten by the fallbackDetector. - */ -static AGIGameDescription g_fallbackDesc = { - { - "", - "", - AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor - Common::UNK_LANG, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_FANMADE, - GType_V2, - GF_FANMADE, - 0x2917, -}; +#include "agi/detection_tables.h" static const ADParams detectionParams = { // Pointer to ADGameDescription or its superset structure @@ -979,11 +145,13 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI + Common::GUIO_NOSPEECH, + // Maximum directory depth + 1, + // List of directory globs + 0 }; -} // End of namespace Agi - using namespace Agi; class AgiMetaEngine : public AdvancedMetaEngine { @@ -1322,6 +490,9 @@ bool AgiBase::canLoadGameStateCurrently() { } bool AgiBase::canSaveGameStateCurrently() { + if (getGameID() == GID_BC) // Technically in Black Cauldron we may save anytime + return true; + return (!(getGameType() == GType_PreAGI) && getflag(fMenusWork) && !_noSaveLoadAllowed && _game.inputEnabled); } diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h new file mode 100644 index 0000000000..711701f55a --- /dev/null +++ b/engines/agi/detection_tables.h @@ -0,0 +1,863 @@ +/* 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$ + * + */ + +namespace Agi { + +using Common::GUIO_NONE; + +#define GAME_LVFPN(id,extra,fname,md5,size,lang,ver,features,gid,platform,interp) { \ + { \ + id, \ + extra, \ + AD_ENTRY1s(fname,md5,size), \ + lang, \ + platform, \ + ADGF_NO_FLAGS, \ + GUIO_NONE \ + }, \ + gid, \ + interp, \ + features, \ + ver, \ + } + +#define GAME_LVFPNF(id,name,fname,md5,size,lang,ver,features,gid,platform,interp) { \ + { \ + id, \ + name, \ + AD_ENTRY1s(fname,md5,size), \ + lang, \ + platform, \ + ADGF_USEEXTRAASTITLE, \ + GUIO_NONE \ + }, \ + gid, \ + interp, \ + features, \ + ver, \ + } + +#define GAME(id,extra,md5,ver,gid) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V2) +#define GAME3(id,extra,fname,md5,ver,gid) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V3) + +#define GAME_P(id,extra,md5,ver,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_V2) + +#define GAME_FP(id,extra,md5,ver,flags,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V2) +#define GAME_F(id,extra,md5,ver,flags,gid) GAME_FP(id,extra,md5,ver,flags,gid,Common::kPlatformPC) + +#define GAME_PS(id,extra,md5,size,ver,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,size,Common::EN_ANY,ver,0,gid,platform,GType_V2) + +#define GAME_LPS(id,extra,md5,size,lang,ver,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,size,lang,ver,0,gid,platform,GType_V2) + +#define GAME_LFPS(id,extra,md5,size,lang,ver,flags,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,size,lang,ver,flags,gid,platform,GType_V2) + +#define GAME3_P(id,extra,fname,md5,ver,flags,gid,platform) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V3) + +#define GAMEpre_P(id,extra,fname,md5,ver,gid,platform) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI) + +#define GAMEpre_PS(id,extra,fname,md5,size,ver,gid,platform) GAME_LVFPN(id,extra,fname,md5,size,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI) + +#define GAME3_PS(id,extra,fname,md5,size,ver,flags,gid,platform) GAME_LVFPN(id,extra,fname,md5,size,Common::EN_ANY,ver,flags,gid,platform,GType_V3) + +#define FANMADE_ILVF(id,name,md5,lang,ver,features) GAME_LVFPNF(id,name,"logdir",md5,-1,lang,ver,(GF_FANMADE|features),GID_FANMADE,Common::kPlatformPC,GType_V2) + +#define FANMADE_ISVP(id,name,md5,size,ver,platform) GAME_LVFPNF(id,name,"logdir",md5,size,Common::EN_ANY,ver,GF_FANMADE,GID_FANMADE,platform,GType_V2) +#define FANMADE_SVP(name,md5,size,ver,platform) FANMADE_ISVP("agi-fanmade",name,md5,size,ver,platform) + +#define FANMADE_LVF(name,md5,lang,ver,features) FANMADE_ILVF("agi-fanmade",name,md5,lang,ver,features) + +#define FANMADE_LF(name,md5,lang,features) FANMADE_LVF(name,md5,lang,0x2917,features) +#define FANMADE_IF(id,name,md5,features) FANMADE_ILVF(id,name,md5,Common::EN_ANY,0x2917,features) + +#define FANMADE_V(name,md5,ver) FANMADE_LVF(name,md5,Common::EN_ANY,ver,0) +#define FANMADE_F(name,md5,features) FANMADE_LF(name,md5,Common::EN_ANY,features) +#define FANMADE_L(name,md5,lang) FANMADE_LF(name,md5,lang,0) +#define FANMADE_I(id,name,md5) FANMADE_IF(id,name,md5,0) + +#define FANMADE(name,md5) FANMADE_F(name,md5,0) + +static const AGIGameDescription gameDescriptions[] = { + + // AGI Demo 1 (PC) 05/87 [AGI 2.425] + GAME("agidemo", "Demo 1 1987-05-20", "9c4a5b09cc3564bc48b4766e679ea332", 0x2440, GID_AGIDEMO), + + // AGI Demo 2 (IIgs) 1.0C (Censored) + GAME_P("agidemo", "Demo 2 1987-11-24 1.0C", "580ffdc569ff158f56fb92761604f70e", 0x2917, GID_AGIDEMO, Common::kPlatformApple2GS), + + // AGI Demo 2 (PC 3.5") 11/87 [AGI 2.915] + GAME("agidemo", "Demo 2 1987-11-24 3.5\"", "e8ebeb0bbe978172fe166f91f51598c7", 0x2917, GID_AGIDEMO), + + // AGI Demo 2 (PC 5.25") 11/87 [v1] [AGI 2.915] + GAME("agidemo", "Demo 2 1987-11-24 [version 1] 5.25\"", "852ac303a374df62571642ca1e2d1f0a", 0x2917, GID_AGIDEMO), + + // AGI Demo 2 (PC 5.25") 01/88 [v2] [AGI 2.917] + GAME("agidemo", "Demo 2 1987-11-25 [version 2] 5.25\"", "1503f02086ea9f388e7e041c039eaa69", 0x2917, GID_AGIDEMO), + + // AGI Demo 3 (PC) 09/88 [AGI 3.002.102] + GAME3("agidemo", "Demo 3 1988-09-13", "dmdir", "289c7a2c881f1d973661e961ced77d74", 0x3149, GID_AGIDEMO), + + // AGI Demo for Kings Quest III and Space Quest I + GAME("agidemo", "Demo Kings Quest III and Space Quest I", "502e6bf96827b6c4d3e67c9cdccd1033", 0x2272, GID_AGIDEMO), + + // Black Cauldron (Amiga) 2.00 6/14/87 + GAME_P("bc", "2.00 1987-06-14", "7b01694af21213b4727bb94476f64eb5", 0x2440, GID_BC, Common::kPlatformAmiga), + + // Black Cauldron (Apple IIgs) 1.0O 2/24/89 (CE) + // Menus not tested + GAME3_P("bc", "1.0O 1989-02-24 (CE)", "bcdir", "dc09d30b147242692f4f85b9811962db", 0x3149, 0, GID_BC, Common::kPlatformApple2GS), + + // Black Cauldron (PC) 2.00 6/14/87 [AGI 2.439] + GAME("bc", "2.00 1987-06-14", "7f598d4712319b09d7bd5b3be10a2e4a", 0x2440, GID_BC), + + // Black Cauldron (Russian) + GAME_LPS("bc", "", "b7de782dfdf8ea7dde8064f09804bcf5", 357, Common::RU_RUS, 0x2440, GID_BC, Common::kPlatformPC), + + // Black Cauldron (PC 5.25") 2.10 11/10/88 [AGI 3.002.098] + GAME3("bc", "2.10 1988-11-10 5.25\"", "bcdir", "0c5a9acbcc7e51127c34818e75806df6", 0x3149, GID_BC), + + // Black Cauldron (PC) 2.10 [AGI 3.002.097] + GAME3("bc", "2.10", "bcdir", "0de3953c9225009dc91e5b0d1692967b", 0x3149, GID_BC), + + // Black Cauldron (CoCo3 360k) [AGI 2.023] + GAME_PS("bc", "", "51212c54808ade96176f201ae0ac7a6f", 357, 0x2440, GID_BC, Common::kPlatformCoCo3), + + // Black Cauldron (CoCo3 360k) [AGI 2.072] + GAME_PS("bc", "updated", "c4e1937f74e8100cd0152b904434d8b4", 357, 0x2440, GID_BC, Common::kPlatformCoCo3), + +// TODO +// These aren't supposed to work now as they require unsupported agi engine 2.01 +#if 0 + // Donald Duck's Playground (Amiga) 1.0C + // Menus not tested + GAME_P("ddp", "1.0C 1987-04-27", "550971d196f65190a5c760d2479406ef", 0x2272, GID_DDP, Common::kPlatformAmiga), + + // Donald Duck's Playground (ST) 1.0A 8/8/86 + // Menus not tested + GAME("ddp", "1.0A 1986-08-08", "64388812e25dbd75f7af1103bc348596", 0x2272, GID_DDP), + + // reported by Filippos (thebluegr) in bugreport #1654500 + // Menus not tested + GAME_PS("ddp", "1.0C 1986-06-09", "550971d196f65190a5c760d2479406ef", 132, 0x2272, GID_DDP, Common::kPlatformPC), +#endif + + // Gold Rush! (Amiga) 1.01 1/13/89 aka 2.05 3/9/89 # 2.316 + GAME3_PS("goldrush", "1.01 1989-01-13 aka 2.05 1989-03-09", "dirs", "a1d4de3e75c2688c1e2ca2634ffc3bd8", 2399, 0x3149, 0, GID_GOLDRUSH, Common::kPlatformAmiga), + + // Gold Rush! (Apple IIgs) 1.0M 2/28/89 (CE) aka 2.01 12/22/88 + // Menus not tested + GAME3_P("goldrush", "1.0M 1989-02-28 (CE) aka 2.01 1988-12-22", "grdir", "3f7b9ce62631434389f85371b11921d6", 0x3149, GF_2GSOLDSOUND, GID_GOLDRUSH, Common::kPlatformApple2GS), + + // Gold Rush! (ST) 1.01 1/13/89 aka 2.01 12/22/88 + GAME3_P("goldrush", "1.01 1989-01-13 aka 2.01 1988-12-22", "grdir", "4dd4d50480a3d6c206fa227ce8142735", 0x3149, 0, GID_GOLDRUSH, Common::kPlatformAtariST), + + // Gold Rush! (PC 5.25") 2.01 12/22/88 [AGI 3.002.149] + GAME3("goldrush", "2.01 1988-12-22 5.25\"", "grdir", "db733d199238d4009a9e95f11ece34e9", 0x3149, GID_GOLDRUSH), + + // Gold Rush! (PC 3.5") 2.01 12/22/88 [AGI 3.002.149] + GAME3("goldrush", "2.01 1988-12-22 3.5\"", "grdir", "6a285235745f69b4b421403659497216", 0x3149, GID_GOLDRUSH), + + // Gold Rush! (PC 3.5", bought from The Software Farm) 3.0 1998-12-22 [AGI 3.002.149] + GAME3("goldrush", "3.0 1998-12-22 3.5\"", "grdir", "6882b6090473209da4cd78bb59f78dbe", 0x3149, GID_GOLDRUSH), + + { + // Gold Rush! (PC 5.25") 2.01 12/22/88 [AGI 3.002.149] + { + "goldrush", + "2.01 1988-12-22", + { + { "grdir", 0, "db733d199238d4009a9e95f11ece34e9", 2399}, + { "vol.0", 0, "4b6423d143674d3757ab1b875d25951d", 25070}, + { NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_GOLDRUSH, + GType_V3, + GF_MACGOLDRUSH, + 0x3149, + }, + + + // Gold Rush! (CoCo3 720k) [AGI 2.023] + GAME_PS("goldrush", "", "0a41b65efc0cd6c4271e957e6ffbbd8e", 744, 0x2440, GID_GOLDRUSH, Common::kPlatformCoCo3), + + // Gold Rush! (CoCo3 360k/720k) [AGI 2.072] + GAME_PS("goldrush", "updated", "c49bf56bf91e31a4601a604e51ef8bfb", 744, 0x2440, GID_GOLDRUSH, Common::kPlatformCoCo3), + + // King's Quest 1 (Amiga) 1.0U # 2.082 + // The original game did not have menus, they are enabled under ScummVM + GAME_FP("kq1", "1.0U 1986", "246c695324f1c514aee2b904fa352fad", 0x2440, GF_MENUS, GID_KQ1, Common::kPlatformAmiga), + + // King's Quest 1 (ST) 1.0V + // The original game did not have menus, they are enabled under ScummVM + GAME_FP("kq1", "1.0V 1986", "c3a017e556c4b0eece366a4cd9abb657", 0x2272, GF_MENUS, GID_KQ1, Common::kPlatformAtariST), + + // King's Quest 1 (IIgs) 1.0S-88223 + // Menus not tested + GAME_P("kq1", "1.0S 1988-02-23", "f4277aa34b43d37382bc424c81627617", 0x2272, GID_KQ1, Common::kPlatformApple2GS), + + // King's Quest 1 (Mac) 2.0C + GAME_P("kq1", "2.0C 1987-03-26", "d4c4739d4ac63f7dbd29255425077d48", 0x2440, GID_KQ1, Common::kPlatformMacintosh), + + // King's Quest 1 (PC 5.25"/3.5") 2.0F [AGI 2.917] + GAME("kq1", "2.0F 1987-05-05 5.25\"/3.5\"", "10ad66e2ecbd66951534a50aedcd0128", 0x2917, GID_KQ1), + + // King's Quest 1 (CoCo3 360k) [AGI 2.023] + GAME_PS("kq1", "", "10ad66e2ecbd66951534a50aedcd0128", 315, 0x2440, GID_KQ1, Common::kPlatformCoCo3), + + // King's Quest 1 (CoCo3 360k) [AGI 2.023] + GAME_PS("kq1", "fixed", "4c8ef8b5d2f1b6c1a93e456d1f1ffc74", 768, 0x2440, GID_KQ1, Common::kPlatformCoCo3), + + // King's Quest 1 (CoCo3 360k) [AGI 2.072] + GAME_PS("kq1", "updated", "94087178c78933a4af3cd24d1c8dd7b2", 315, 0x2440, GID_KQ1, Common::kPlatformCoCo3), + + // King's Quest 2 (IIgs) 2.0A 6/16/88 (CE) + GAME_P("kq2", "2.0A 1988-06-16 (CE)", "5203c8b95250a2ecfee93ddb99414753", 0x2917, GID_KQ2, Common::kPlatformApple2GS), + + // King's Quest 2 (Amiga) 2.0J (Broken) + GAME_P("kq2", "2.0J 1987-01-29 [OBJECT decrypted]", "b866f0fab2fad91433a637a828cfa410", 0x2440, GID_KQ2, Common::kPlatformAmiga), + + // King's Quest 2 (Mac) 2.0R + GAME_P("kq2", "2.0R 1988-03-23", "cbdb0083317c8e7cfb7ac35da4bc7fdc", 0x2440, GID_KQ2, Common::kPlatformMacintosh), + + // King's Quest 2 (PC) 2.1 [AGI 2.411]; entry from DAGII, but missing from Sarien? + // XXX: any major differences from 2.411 to 2.440? + GAME("kq2", "2.1 1987-04-10", "759e39f891a0e1d86dd29d7de485c6ac", 0x2440, GID_KQ2), + + // King's Quest 2 (PC 5.25"/3.5") 2.2 [AGI 2.426] + GAME("kq2", "2.2 1987-05-07 5.25\"/3.5\"", "b944c4ff18fb8867362dc21cc688a283", 0x2917, GID_KQ2), + + // King's Quest 2 (Russian) + GAME_LPS("kq2", "", "35211c574ececebdc723b23e35f99275", 543, Common::RU_RUS, 0x2917, GID_KQ2, Common::kPlatformPC), + + // King's Quest 2 (CoCo3 360k) [AGI 2.023] + GAME_PS("kq2", "", "b944c4ff18fb8867362dc21cc688a283", 543, 0x2440, GID_KQ2, Common::kPlatformCoCo3), + + // King's Quest 2 (CoCo3 360k) [AGI 2.072] + GAME_PS("kq2", "updated", "f64a606de740a5348f3d125c03e989fe", 543, 0x2440, GID_KQ2, Common::kPlatformCoCo3), + + // King's Quest 2 (CoCo3 360k) [AGI 2.023] + GAME_PS("kq2", "fixed", "fb33ac2768a94a89117a270771db465c", 768, 0x2440, GID_KQ2, Common::kPlatformCoCo3), + + // King's Quest 3 (Amiga) 1.01 11/8/86 + // The original game did not have menus, they are enabled under ScummVM + GAME_FP("kq3", "1.01 1986-11-08", "8ab343306df0e2d98f136be4e8cfd0ef", 0x2440, GF_MENUS, GID_KQ3, Common::kPlatformAmiga), + + // King's Quest 3 (ST) 1.02 11/18/86 + // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game + GAME_FP("kq3", "1.02 1986-11-18", "8846df2654302b623217ba8bd6d657a9", 0x2272, GF_ESCPAUSE, GID_KQ3, Common::kPlatformAtariST), + + // King's Quest 3 (Mac) 2.14 3/15/88 + GAME_P("kq3", "2.14 1988-03-15", "7639c0da5ce94848227d409351fabda2", 0x2440, GID_KQ3, Common::kPlatformMacintosh), + + // King's Quest 3 (IIgs) 2.0A 8/28/88 (CE) + GAME_P("kq3", "2.0A 1988-08-28 (CE)", "ac30b7ca5a089b5e642fbcdcbe872c12", 0x2917, GID_KQ3, Common::kPlatformApple2GS), + + // King's Quest 3 (Amiga) 2.15 11/15/89 # 2.333 + // Original pauses with ESC, has menus accessible with mouse. + // ver = 0x3086 -> menus accessible with ESC or mouse, bug #2835581 (KQ3: Game Crash When Leaving Tavern as Fly). + // ver = 0x3149 -> menus accessible with mouse, ESC pauses game, bug #2835581 disappears. + GAME3_PS("kq3", "2.15 1989-11-15", "dirs", "8e35bded2bc5cf20f5eec2b15523b155", 1805, 0x3149, 0, GID_KQ3, Common::kPlatformAmiga), + + // King's Quest 3 (PC) 1.01 11/08/86 [AGI 2.272] + // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game + GAME_FP("kq3", "1.01 1986-11-08", "9c2b34e7ffaa89c8e2ecfeb3695d444b", 0x2272, GF_ESCPAUSE, GID_KQ3, Common::kPlatformPC), + + // King's Quest 3 (Russian) + GAME_LFPS("kq3", "", "5856dec6ccb9c4b70aee21044a19270a", 390, Common::RU_RUS, 0x2272, GF_ESCPAUSE, GID_KQ3, Common::kPlatformPC), + + // King's Quest 3 (PC 5.25") 2.00 5/25/87 [AGI 2.435] + GAME("kq3", "2.00 1987-05-25 5.25\"", "18aad8f7acaaff760720c5c6885b6bab", 0x2440, GID_KQ3), + + // King's Quest 3 (Mac) 2.14 3/15/88 + // Menus not tested + GAME_P("kq3", "2.14 1988-03-15 5.25\"", "7650e659c7bc0f1e9f8a410b7a2e9de6", 0x2440, GID_KQ3, Common::kPlatformMacintosh), + + // King's Quest 3 (PC 3.5") 2.14 3/15/88 [AGI 2.936] + GAME("kq3", "2.14 1988-03-15 3.5\"", "d3d17b77b3b3cd13246749231d9473cd", 0x2936, GID_KQ3), + + // King's Quest 3 (CoCo3 158k/360k) [AGI 2.023] + GAME_PS("kq3", "", "5a6be7d16b1c742c369ef5cc64fefdd2", 429, 0x2440, GID_KQ3, Common::kPlatformCoCo3), + + // King's Quest 4 (PC 5.25") 2.0 7/27/88 [AGI 3.002.086] + GAME3("kq4", "2.0 1988-07-27", "kq4dir", "f50f7f997208ca0e35b2650baec43a2d", 0x3086, GID_KQ4), + + // King's Quest 4 (PC 3.5") 2.0 7/27/88 [AGI 3.002.086] + GAME3("kq4", "2.0 1988-07-27 3.5\"", "kq4dir", "fe44655c42f16c6f81046fdf169b6337", 0x3086, GID_KQ4), + + // King's Quest 4 (PC 3.5") 2.2 9/27/88 [AGI 3.002.086] + // Menus not tested + GAME3("kq4", "2.2 1988-09-27 3.5\"", "kq4dir", "7470b3aeb49d867541fc66cc8454fb7d", 0x3086, GID_KQ4), + + // King's Quest 4 (PC 5.25") 2.3 9/27/88 [AGI 3.002.086] + GAME3("kq4", "2.3 1988-09-27", "kq4dir", "6d7714b8b61466a5f5981242b993498f", 0x3086, GID_KQ4), + + // King's Quest 4 (PC 3.5") 2.3 9/27/88 [AGI 3.002.086] + GAME3("kq4", "2.3 1988-09-27 3.5\"", "kq4dir", "82a0d39af891042e99ac1bd6e0b29046", 0x3086, GID_KQ4), + + // King's Quest 4 (IIgs) 1.0K 11/22/88 (CE) + // Menus not tested + GAME3_P("kq4", "1.0K 1988-11-22", "kq4dir", "8536859331159f15012e35dc82cb154e", 0x3086, 0, GID_KQ4, Common::kPlatformApple2GS), + + // King's Quest 4 demo (PC) [AGI 3.002.102] + // Menus not tested + GAME3("kq4", "Demo 1988-12-20", "dmdir", "a3332d70170a878469d870b14863d0bf", 0x3149, GID_KQ4), + + // King's Quest 4 (CoCo3 720k) [AGI 2.023] + GAME_PS("kq4", "", "9e7729a28e749ca241d2bf71b9b2dbde", 741, 0x2440, GID_KQ4, Common::kPlatformCoCo3), + + // King's Quest 4 (CoCo3 360k/720k) [AGI 2.072] + GAME_PS("kq4", "updated", "1959ca10739edb34069bb504dbd74805", 741, 0x2440, GID_KQ4, Common::kPlatformCoCo3), + + // Leisure Suit Larry 1 (PC 5.25"/3.5") 1.00 6/1/87 [AGI 2.440] + GAME("lsl1", "1.00 1987-06-01 5.25\"/3.5\"", "1fe764e66857e7f305a5f03ca3f4971d", 0x2440, GID_LSL1), + + // Leisure Suit Larry 1 Polish + GAME_LPS("lsl1", "2.00 2001-12-11", "7ba1fccc46d27c141e704706c1d0a85f", 303, Common::PL_POL, 0x2440, GID_LSL1, Common::kPlatformPC), + + // Leisure Suit Larry 1 Polish - Demo + GAME_LPS("lsl1", "Demo", "3b2f564306c401dff6334441df967ddd", 666, Common::PL_POL, 0x2917, GID_LSL1, Common::kPlatformPC), + + // Leisure Suit Larry 1 (ST) 1.04 6/18/87 + GAME_P("lsl1", "1.04 1987-06-18", "8b579f8673fe9448c2538f5ed9887cf0", 0x2440, GID_LSL1, Common::kPlatformAtariST), + + // Leisure Suit Larry 1 (Amiga) 1.05 6/26/87 # x.yyy + GAME_P("lsl1", "1.05 1987-06-26", "3f5d26d8834ca49c147fb60936869d56", 0x2440, GID_LSL1, Common::kPlatformAmiga), + + // Leisure Suit Larry 1 (IIgs) 1.0E + GAME_P("lsl1", "1.0E 1987", "5f9e1dd68d626c6d303131c119582ad4", 0x2440, GID_LSL1, Common::kPlatformApple2GS), + + // Leisure Suit Larry 1 (Mac) 1.05 6/26/87 + GAME_P("lsl1", "1.05 1987-06-26", "8a0076429890531832f0dc113285e31e", 0x2440, GID_LSL1, Common::kPlatformMacintosh), + + // Leisure Suit Larry 1 (CoCo3 158k/360k) [AGI 2.072] + GAME_PS("lsl1", "", "a2de1fe76565c3e8b40c9d036b5e5612", 198, 0x2440, GID_LSL1, Common::kPlatformCoCo3), + + // Manhunter NY (ST) 1.03 10/20/88 + GAME3_P("mh1", "1.03 1988-10-20", "mhdir", "f2d58056ad802452d60776ee920a52a6", 0x3149, 0, GID_MH1, Common::kPlatformAtariST), + + // Manhunter NY (IIgs) 2.0E 10/05/88 (CE) + GAME3_P("mh1", "2.0E 1988-10-05 (CE)", "mhdir", "2f1509f76f24e6e7d213f2dadebbf156", 0x3149, 0, GID_MH1, Common::kPlatformApple2GS), + + // Manhunter NY (Amiga) 1.06 3/18/89 + GAME3_P("mh1", "1.06 1989-03-18", "dirs", "92c6183042d1c2bb76236236a7d7a847", 0x3149, GF_OLDAMIGAV20, GID_MH1, Common::kPlatformAmiga), + + // reported by Filippos (thebluegr) in bugreport #1654500 + // Manhunter NY (PC 5.25") 1.22 8/31/88 [AGI 3.002.107] + GAME3_PS("mh1", "1.22 1988-08-31", "mhdir", "0c7b86f05fe02c2e26cff1b07450b82a", 2123, 0x3149, 0, GID_MH1, Common::kPlatformPC), + + // Manhunter NY (PC 3.5") 1.22 8/31/88 [AGI 3.002.102] + GAME3_PS("mh1", "1.22 1988-08-31", "mhdir", "5b625329021ad49fd0c1d6f2d6f54bba", 2141, 0x3149, 0, GID_MH1, Common::kPlatformPC), + + // Manhunter NY (CoCo3 720k) [AGI 2.023] + GAME_PS("mh1", "", "b968285caf2f591c78dd9c9e26ab8974", 495, 0x2440, GID_MH1, Common::kPlatformCoCo3), + + // Manhunter NY (CoCo3 360k/720k) [AGI 2.072] + GAME_PS("mh1", "updated", "d47da950c62289f8d4ccf36af73365f2", 495, 0x2440, GID_MH1, Common::kPlatformCoCo3), + + // Manhunter SF (ST) 1.0 7/29/89 + GAME3_P("mh2", "1.0 1989-07-29", "mh2dir", "5e3581495708b952fea24438a6c7e040", 0x3149, 0, GID_MH1, Common::kPlatformAtariST), + + // Manhunter SF (Amiga) 3.06 8/17/89 # 2.333 + GAME3_PS("mh2", "3.06 1989-08-17", "dirs", "b412e8a126368b76696696f7632d4c16", 2573, 0x3086, GF_OLDAMIGAV20, GID_MH2, Common::kPlatformAmiga), + + // Manhunter SF (PC 5.25") 3.03 8/17/89 [AGI 3.002.149] + GAME3("mh2", "3.03 1989-08-17 5.25\"", "mh2dir", "b90e4795413c43de469a715fb3c1fa93", 0x3149, GID_MH2), + + // Manhunter SF (PC 3.5") 3.02 7/26/89 [AGI 3.002.149] + GAME3("mh2", "3.02 1989-07-26 3.5\"", "mh2dir", "6fb6f0ee2437704c409cf17e081ba152", 0x3149, GID_MH2), + + // Manhunter SF (CoCo3 720k) [AGI 2.023] + GAME_PS("mh2", "", "acaaa577e10d1753c5a74f6ae1d858d4", 591, 0x2440, GID_MH2, Common::kPlatformCoCo3), + + // Manhunter SF (CoCo3 720k) [AGI 2.072] + GAME_PS("mh2", "updated", "c64875766700196e72a92359f70f45a9", 591, 0x2440, GID_MH2, Common::kPlatformCoCo3), + + // Mickey's Space Adventure + // Preagi game + GAMEpre_P("mickey", "", "1.pic", "b6ec04c91a05df374792872c4d4ce66d", 0x0000, GID_MICKEY, Common::kPlatformPC), + +#if 0 + // Mixed-Up Mother Goose (Amiga) 1.1 + // Problematic: crashes + // Menus not tested + GAME3_PS("mixedup", "1.1 1986-12-10", "dirs", "5c1295fe6daaf95831195ba12894dbd9", 2021, 0x3086, 0, GID_MIXEDUP, Common::kPlatformAmiga), +#endif + + // Mixed Up Mother Goose (IIgs) + GAME_P("mixedup", "1987", "3541954a7303467c6df87665312ffb6a", 0x2917, GID_MIXEDUP, Common::kPlatformApple2GS), + + // Mixed-Up Mother Goose (PC) [AGI 2.915] + GAME("mixedup", "1987-11-10", "e524655abf9b96a3b179ffcd1d0f79af", 0x2917, GID_MIXEDUP), + + // Mixed-Up Mother Goose (CoCo3 360k) [AGI 2.072] + GAME_PS("mixedup", "", "44e63e9b4d4822a31edea0e8a7e7eac4", 606, 0x2440, GID_MIXEDUP, Common::kPlatformCoCo3), + + // Police Quest 1 (PC) 2.0E 11/17/87 [AGI 2.915] + GAME("pq1", "2.0E 1987-11-17", "2fd992a92df6ab0461d5a2cd83c72139", 0x2917, GID_PQ1), + + // Police Quest 1 (Mac) 2.0G 12/3/87 + GAME_P("pq1", "2.0G 1987-12-03", "805750b66c1c5b88a214e67bfdca17a1", 0x2440, GID_PQ1, Common::kPlatformMacintosh), + + // Police Quest 1 (IIgs) 2.0B-88421 + GAME_P("pq1", "2.0B 1988-04-21", "e7c175918372336461e3811d594f482f", 0x2917, GID_PQ1, Common::kPlatformApple2GS), + + // Police Quest 1 (Amiga) 2.0B 2/22/89 # 2.310 + GAME3_PS("pq1", "2.0B 1989-02-22", "dirs", "cfa93e5f2aa7378bddd10ad6746a2ffb", 1613, 0x3149, 0, GID_PQ1, Common::kPlatformAmiga), + + // Police Quest 1 (IIgs) 2.0A-88318 + GAME_P("pq1", "2.0A 1988-03-18", "8994e39d0901de3d07cecfb954075bb5", 0x2917, GID_PQ1, Common::kPlatformApple2GS), + + // Police Quest 1 (PC) 2.0A 10/23/87 [AGI 2.903/2.911] + GAME("pq1", "2.0A 1987-10-23", "b9dbb305092851da5e34d6a9f00240b1", 0x2917, GID_PQ1), + + // Police Quest 1 (Russian) + GAME_LPS("pq1", "", "604cc8041d24c4c7e5fa8baf386ef76e", 360, Common::RU_RUS, 0x2917, GID_PQ1, Common::kPlatformPC), + + // Police Quest 1 2.0G 12/3/87 + GAME("pq1", "2.0G 1987-12-03 5.25\"/ST", "231f3e28170d6e982fc0ced4c98c5c1c", 0x2440, GID_PQ1), + + // Police Quest 1 (PC) 2.0G 12/3/87; entry from DAGII, but missing from Sarien? + // not sure about disk format -- dsymonds + GAME("pq1", "2.0G 1987-12-03", "d194e5d88363095f55d5096b8e32fbbb", 0x2917, GID_PQ1), + + // Police Quest 1 (CoCo3 360k) [AGI 2.023] + GAME_PS("pq1", "", "28a077041f75aab78f66804800940085", 375, 0x2440, GID_PQ1, Common::kPlatformCoCo3), + + // Police Quest 1 (CoCo3 360k) [AGI 2.072] + GAME_PS("pq1", "updated", "63b9a9c6eec154751dd446cd3693e0e2", 768, 0x2440, GID_PQ1, Common::kPlatformCoCo3), + + // Space Quest 1 (ST) 1.1A + // The original game did not have menus, they are enabled under ScummVM + GAME_FP("sq1", "1.1A 1986-02-06", "6421fb64b0e6604c9dd065975d9279e9", 0x2440, GF_MENUS, GID_SQ1, Common::kPlatformAtariST), + + // Space Quest 1 (PC 360k) 1.1A [AGI 2.272] + // The original game did not have menus, they are enabled under ScummVM + GAME_FP("sq1", "1.1A 1986-11-13", "8d8c20ab9f4b6e4817698637174a1cb6", 0x2272, GF_MENUS, GID_SQ1, Common::kPlatformPC), + + // Space Quest 1 (PC 720k) 1.1A [AGI 2.272] + // The original game did not have menus, they are enabled under ScummVM + GAME_FP("sq1", "1.1A 720kb", "0a92b1be7daf3bb98caad3f849868aeb", 0x2272, GF_MENUS, GID_SQ1, Common::kPlatformPC), + + // Space Quest 1 (Amiga) 1.2 # 2.082 + // The original game did not have menus, they are enabled under ScummVM + GAME_FP("sq1", "1.2 1986", "0b216d931e95750f1f4837d6a4b821e5", 0x2440, GF_MENUS | GF_OLDAMIGAV20, GID_SQ1, Common::kPlatformAmiga), + + // Space Quest 1 (Mac) 1.5D + GAME_P("sq1", "1.5D 1987-04-02", "ce88419aadd073d1c6682d859b3d8aa2", 0x2440, GID_SQ1, Common::kPlatformMacintosh), + + // Space Quest 1 (IIgs) 2.2 + GAME_P("sq1", "2.2 1987", "64b9b3d04c1066d36e6a6e56187a83f7", 0x2917, GID_SQ1, Common::kPlatformApple2GS), + + // Space Quest 1 (PC) 1.0X [AGI 2.089] + // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game + GAME_FP("sq1", "1.0X 1986-09-24", "af93941b6c51460790a9efa0e8cb7122", 0x2089, GF_ESCPAUSE, GID_SQ1, Common::kPlatformPC), + + // Space Quest 1 (Russian) + GAME_LFPS("sq1", "", "a279eb8ddbdefdb1ea6adc827a1d632a", 372, Common::RU_RUS, 0x2089, GF_ESCPAUSE, GID_SQ1, Common::kPlatformPC), + + // Space Quest 1 (PC 5.25"/3.5") 2.2 [AGI 2.426/2.917] + GAME("sq1", "2.2 1987-05-07 5.25\"/3.5\"", "5d67630aba008ec5f7f9a6d0a00582f4", 0x2440, GID_SQ1), + + // Space Quest 1 (CoCo3 360k) [AGI 2.072] + GAME_PS("sq1", "", "5d67630aba008ec5f7f9a6d0a00582f4", 372, 0x2440, GID_SQ1, Common::kPlatformCoCo3), + + // Space Quest 1 (CoCo3 360k) [AGI 2.023] + GAME_PS("sq1", "fixed", "ca822b768b6462e410423ea7f498daee", 768, 0x2440, GID_SQ1, Common::kPlatformCoCo3), + + // Space Quest 1 (CoCo3 360k) [AGI 2.072] + GAME_PS("sq1", "updated", "7fa54e6bb7ffeb4cf20eca39d86f5fb2", 387, 0x2440, GID_SQ1, Common::kPlatformCoCo3), + + // Space Quest 2 (PC 3.5") 2.0D [AGI 2.936] + GAME("sq2", "2.0D 1988-03-14 3.5\"", "85390bde8958c39830e1adbe9fff87f3", 0x2936, GID_SQ2), + + // Space Quest 2 (IIgs) 2.0A 7/25/88 (CE) + GAME_P("sq2", "2.0A 1988-07-25 (CE)", "5dfdac98dd3c01fcfb166529f917e911", 0x2936, GID_SQ2, Common::kPlatformApple2GS), + + { + // Space Quest 2 (Amiga) 2.0F + { + "sq2", + "2.0F 1986-12-09 [VOL.2->PICTURE.16 broken]", + { + { "logdir", 0, "28add5125484302d213911df60d2aded", 426}, + { "object", 0, "5dc52be721257719f4b311a84ce22b16", 372}, + { NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_SQ2, + GType_V2, + 0, + 0x2936, + }, + + + // Space Quest 2 (Mac) 2.0D + GAME_P("sq2", "2.0D 1988-04-04", "bfbebe0b59d83f931f2e1c62ce9484a7", 0x2936, GID_SQ2, Common::kPlatformMacintosh), + + // reported by Filippos (thebluegr) in bugreport #1654500 + // Space Quest 2 (PC 5.25") 2.0A [AGI 2.912] + GAME_PS("sq2", "2.0A 1987-11-06 5.25\"", "ad7ce8f800581ecc536f3e8021d7a74d", 423, 0x2917, GID_SQ2, Common::kPlatformPC), + + // Space Quest 2 (Russian) + GAME_LPS("sq2", "", "ba21c8934caf28e3ba45ce7d1cd6b041", 423, Common::RU_RUS, 0x2917, GID_SQ2, Common::kPlatformPC), + + // Space Quest 2 (PC 3.5") 2.0A [AGI 2.912] + GAME_PS("sq2", "2.0A 1987-11-06 3.5\"", "6c25e33d23b8bed42a5c7fa63d588e5c", 423, 0x2917, GID_SQ2, Common::kPlatformPC), + + // Space Quest 2 (PC 5.25"/ST) 2.0C/A [AGI 2.915] + // Menus not tested + GAME("sq2", "2.0C/A 5.25\"/ST", "bd71fe54869e86945041700f1804a651", 0x2917, GID_SQ2), + + // Space Quest 2 (PC 3.5") 2.0F [AGI 2.936] + GAME("sq2", "2.0F 1989-01-05 3.5\"", "28add5125484302d213911df60d2aded", 0x2936, GID_SQ2), + + // Space Quest 2 (CoCo3 360k) [AGI 2.023] + GAME_PS("sq2", "", "12973d39b892dc9d280257fd271e9597", 768, 0x2440, GID_SQ2, Common::kPlatformCoCo3), + + // Space Quest 2 (CoCo3 360k) [AGI 2.072] + GAME_PS("sq2", "updated", "d24f19b047e65e1763eff4b46f3d50df", 768, 0x2440, GID_SQ2, Common::kPlatformCoCo3), + + // Troll's Tale + GAMEpre_PS("troll", "", "troll.img", "62903f264b3d849be4214b3a5c42a2fa", 184320, 0x0000, GID_TROLL, Common::kPlatformPC), + + // Winnie the Pooh in the Hundred Acre Wood + GAMEpre_P("winnie", "", "title.pic", "2e7900c1ccaa7671d65405f6d1efed30", 0x0000, GID_WINNIE, Common::kPlatformPC), + + // Winnie the Pooh in the Hundred Acre Wood (Amiga) + GAMEpre_P("winnie", "", "title", "2e7900c1ccaa7671d65405f6d1efed30", 0x0000, GID_WINNIE, Common::kPlatformAmiga), + + // Winnie the Pooh in the Hundred Acre Wood (C64) + GAMEpre_P("winnie", "", "title.pic", "d4eb97cffc866110f71e1ec9f84fe643", 0x0000, GID_WINNIE, Common::kPlatformC64), + + // Winnie the Pooh in the Hundred Acre Wood (Apple //gs) + GAMEpre_P("winnie", "", "title.pic", "45e06010a3c61d78f4661103c901ae11", 0x0000, GID_WINNIE, Common::kPlatformApple2GS), + + // Xmas Card 1986 (PC) [AGI 2.272] + GAME("xmascard", "1986-11-13 [version 1]", "3067b8d5957e2861e069c3c0011bd43d", 0x2272, GID_XMASCARD), + + // Xmas Card 1986 (CoCo3 360k) [AGI 2.072] + GAME_PS("xmascard", "", "25ad35e9628fc77e5e0dd35852a272b6", 768, 0x2440, GID_XMASCARD, Common::kPlatformCoCo3), + + FANMADE_F("2 Player Demo", "4279f46b3cebd855132496476b1d2cca", GF_AGIMOUSE), + FANMADE("AGI Contest 1 Template", "d879aed25da6fc655564b29567358ae2"), + FANMADE("AGI Contest 2 Template", "5a2fb2894207eff36c72f5c1b08bcc07"), + FANMADE("AGI Mouse Demo 0.60 demo 1", "c07e2519de674c67386cb2cc6f2e3904"), + FANMADE("AGI Mouse Demo 0.60 demo 2", "cc49d8b88ed6faf4f53ce92c84e0fe1b"), + FANMADE("AGI Mouse Demo 0.70", "3497c291e4afb6f758e61740678a2aec"), + FANMADE_F("AGI Mouse Demo 1.00", "20397f0bf0ef936f416bb321fb768fc7", GF_AGIMOUSE), + FANMADE_F("AGI Mouse Demo 1.10", "f4ad396b496d6167635ad0b410312ab8", GF_AGIMOUSE|GF_AGIPAL), + FANMADE("AGI Piano (v1.0)", "8778b3d89eb93c1d50a70ef06ef10310"), + FANMADE("AGI Quest (v1.46-TJ0)", "1cf1a5307c1a0a405f5039354f679814"), + GAME("tetris", "", "7a874e2db2162e7a4ce31c9130248d8a", 0x2917, GID_FANMADE), + FANMADE_V("AGI Trek (Demo)", "c02882b8a8245b629c91caf7eb78eafe", 0x2440), + FANMADE_F("AGI256 Demo", "79261ac143b2e2773b2753674733b0d5", GF_AGI256), + FANMADE_F("AGI256-2 Demo", "3cad9b3aff1467cebf0c5c5b110985c5", GF_AGI256_2), + FANMADE_LF("Abrah: L'orphelin de l'espace (v1.2)", "b7b6d1539e14d5a26fa3088288e1badc", Common::FR_FRA, GF_AGIPAL), + FANMADE("Acidopolis", "7017db1a4b726d0d59e65e9020f7d9f7"), + FANMADE("Agent 0055 (v1.0)", "c2b34a0c77acb05482781dda32895f24"), + FANMADE("Agent 06 vs. The Super Nazi", "136f89ca9f117c617e88a85119777529"), + FANMADE("Agent Quest", "59e49e8f72058a33c00d60ee1097e631"), + FANMADE("Al Pond - On Holiday (v1.0)", "a84975496b42d485920e886e92eed68b"), + FANMADE("Al Pond - On Holiday (v1.1)", "7c95ac4689d0c3bfec61e935f3093634"), + FANMADE("Al Pond - On Holiday (v1.3)", "8f30c260de9e1dd3d8b8f89cc19d2633"), + FANMADE("Al Pond 1 - Al Lives Forever (v1.0)", "e8921c3043b749b056ff51f56d1b451b"), + FANMADE("Al Pond 1 - Al Lives Forever (v1.3)", "fb4699474054962e0dbfb4cf12ca52f6"), + FANMADE("Apocalyptic Quest (v0.03 Teaser)", "42ced528b67965d3bc3b52c635f94a57"), + FANMADE_F("Apocalyptic Quest (v4.00 Alpha 1)", "e15581628d84949b8d352d224ec3184b", GF_AGIMOUSE), + FANMADE_F("Apocalyptic Quest (v4.00 Alpha 2)", "0eee850005860e46345b38fea093d194", GF_AGIMOUSE), + FANMADE_F("Band Quest (Demo)", "7326abefd793571cc17ed0db647bdf34", GF_AGIMOUSE), + FANMADE_F("Band Quest (Early Demo)", "de4758dd34676b248c8301b32d93bc6f", GF_AGIMOUSE), + FANMADE("Beyond the Titanic 2", "9b8de38dc64ffb3f52b7877ea3ebcef9"), + FANMADE("Biri Quest 1", "1b08f34f2c43e626c775c9d6649e2f17"), + FANMADE("Bob The Farmboy", "e4b7df9d0830addee5af946d380e66d7"), + FANMADE_F("Boring Man 1: The Toad to Robinland", "d74481cbd227f67ace37ce6a5493039f", GF_AGIMOUSE), + FANMADE_F("Boring Man 2: Ho Man! This Game Sucks!", "250032ba105bdf7c1bc4fed767c2d37e", GF_AGIMOUSE), + FANMADE("Botz", "a8fabe4e807adfe5ec02bfec6d983695"), + FANMADE("Brian's Quest (v1.0)", "0964aa79b9cdcff7f33a12b1d7e04b9c"), + FANMADE("CPU-21 (v1.0)", "35b7cdb4d17e890e4c52018d96e9cbf4"), + GAME("caitlyn", "Demo", "5b8a3cdb2fc05469f8119d49f50fbe98", 0x2917, GID_FANMADE), + GAME("caitlyn", "", "818469c484cae6dad6f0e9a353f68bf8", 0x2917, GID_FANMADE), + FANMADE("Car Driver (v1.1)", "2311611d2d36d20ccc9da806e6cba157"), + FANMADE("Cloak of Darkness (v1.0)", "5ba6e18bf0b53be10db8f2f3831ee3e5"), + FANMADE("Coco Coq (English) - Coco Coq In Grostesteing's Base (v.1.0.3)", "97631f8e710544a58bd6da9e780f9320"), + FANMADE_L("Coco Coq (French) - Coco Coq Dans la Base de Grostesteing (v1.0.2)", "ef579ebccfe5e356f9a557eb3b2d8649", Common::FR_FRA), + FANMADE("Corby's Murder Mystery (v1.0)", "4ebe62ac24c5a8c7b7898c8eb070efe5"), + FANMADE_F("DG: The AGIMouse Adventure (English v1.1)", "efe453b92bc1487ea69fbebede4d5f26", GF_AGIMOUSE|GF_AGIPAL), + FANMADE_LF("DG: The AGIMouse Adventure (French v1.1)", "eb3d17ca466d672cbb95947e8d6e846a", Common::FR_FRA, GF_AGIMOUSE|GF_AGIPAL), + FANMADE("DG: The Adventure Game (English v1.1)", "0d6376d493fa7a21ec4da1a063e12b25"), + FANMADE_L("DG: The Adventure Game (French v1.1)", "258bdb3bb8e61c92b71f2f456cc69e23", Common::FR_FRA), + FANMADE("Dashiki (16 Colors)", "9b2c7b9b0283ab9f12bedc0cb6770a07"), + FANMADE_F("Dashiki (256 Colors)", "c68052bb209e23b39b55ff3d759958e6", GF_AGIMOUSE|GF_AGI256), + FANMADE("Date Quest 1 (v1.0)", "ba3dcb2600645be53a13170aa1a12e69"), + FANMADE("Date Quest 2 (v1.0 Demo)", "1602d6a2874856e928d9a8c8d2d166e9"), + FANMADE("Date Quest 2 (v1.0)", "f13f6fc85aa3e6e02b0c20408fb63b47"), + FANMADE("Dave's Quest (v0.07)", "f29c3660de37bacc1d23547a167f27c9"), + FANMADE("Dave's Quest (v0.17)", "da3772624cc4a86f7137db812f6d7c39"), + FANMADE("Disco Nights (Demo)", "dc5a2b21182ba38bdcd992a3a978e690"), + FANMADE("Dogs Quest - The Quest for the Golden Bone (v1.0)", "f197357edaaea0ff70880602d2f09b3e"), + FANMADE("Dr. Jummybummy's Space Adventure", "988bd81785f8a452440a2a8ac67f96aa"), + FANMADE("Ed Ward", "98be839b9f30cbedea4c9cee5442d827"), + FANMADE("Elfintard", "c3b847e9e9e978af9708df76a0751dc2"), + FANMADE("Enclosure (v1.01)", "f08e66fee9ecdde77db7ee9a10c96ba2"), + FANMADE("Enclosure (v1.03)", "e4a0613ed02401502e506ba3565a8c40"), + FANMADE_SVP("Enclosure", "fe98e6126db74c6cc6fd8fe395cc6e8c", 345, 0x2440, Common::kPlatformCoCo3), + FANMADE("Epic Fighting (v0.1)", "aff24a1b3bdd676187685c4d95ba4294"), + FANMADE("Escape Quest (v0.0.3)", "2346b65619b1da0298b715b06d1a45a1"), + FANMADE("Escape from the Desert (beta 1)", "dfdc634d340854bd6ece28024010758d"), + FANMADE("Escape from the Salesman", "e723ca4fe0f6f56affe039fbb4dbeb6c"), + FANMADE("Fu$k Quest 1 (final)", "1cd0587422313f6ca77d6a95988e88ed"), + FANMADE("Fu$k Quest 1", "1cd0587422313f6ca77d6a95988e88ed"), + FANMADE("Fu$k Quest 2 - Romancing the Bone (Teaser)", "d288355d71d9bb1639260ccaa3b2fbfe"), + FANMADE("Fu$k Quest 2 - Romancing the Bone", "294beeb7765c7ea6b05ed7b9bf7bff4f"), + FANMADE("Gennadi Tahab Autot - Mission Pack 1 - Kuressaare", "bfa5fe71978e6ccf3d4eedd430124015"), + FANMADE("Go West, Young Hippie", "ff31484ea465441cb5f3a0f8e956b716"), + FANMADE("Good Man (demo v3.41)", "3facd8a8f856b7b6e0f6c3200274d88c"), + + { + // Groza + { + "agi-fanmade", + "Groza (russian) [AGDS sample]", + AD_ENTRY1("logdir", "421da3a18004122a966d64ab6bd86d2e"), + Common::RU_RUS, + Common::kPlatformPC, + ADGF_USEEXTRAASTITLE, + GUIO_NONE + }, + GID_FANMADE, + GType_V2, + GF_AGDS, + 0x2440, + }, + + { + // Get Outta SQ + { + "agi-fanmade", + "Get Outta Space Quest", + AD_ENTRY1("logdir", "aaea5b4a348acb669d13b0e6f22d4dc9"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_USEEXTRAASTITLE, + GUIO_NONE + }, + GID_GETOUTTASQ, + GType_V2, + 0, + 0x2440, + }, + + FANMADE_F("Half-Death - Terror At White-Mesa", "b62c05d0ace878261392073f57ae788c", GF_AGIMOUSE), + FANMADE("Hank's Quest (v1.0 English) - Victim of Society", "64c15b3d0483d17888129100dc5af213"), + FANMADE("Hank's Quest (v1.1 English) - Victim of Society", "86d1f1dd9b0c4858d096e2a60cca8a14"), + FANMADE_L("Hank's Quest (v1.81 Dutch) - Slachtoffer Van Het Gebeuren", "41e53972d55ff3dff9e90d15fe1b659f", Common::NL_NLD), + FANMADE("Hank's Quest (v1.81 English) - Victim of Society", "7a776383282f62a57c3a960dafca62d1"), + FANMADE("Herbao (v0.2)", "6a5186fc8383a9060517403e85214fc2"), + FANMADE_F("Hitler's Legacy (v.0004q)", "a412881269ba34584bd0a3268e5a9863", GF_AGIMOUSE), + FANMADE("Hobbits", "4a1c1ef3a7901baf0ab45fde0cfadd89"), + FANMADE_F("Isabella Coq - A Present For My Dad", "55c6819f2330c4d5d6459874c9f123d9", GF_AGIMOUSE), + FANMADE("Jack & Julia - VAMPYR", "8aa0b9a26f8d5a4421067ab8cc3706f6"), + FANMADE("Jeff's Quest (v.5 alpha Jun 1)", "10f1720eed40c12b02a0f32df3e72ded"), + FANMADE("Jeff's Quest (v.5 alpha May 31)", "51ff71c0ed90db4e987a488ed3bf0551"), + FANMADE("Jen's Quest (Demo 1)", "361afb5bdb6160213a1857245e711939"), + FANMADE("Jen's Quest (Demo 2)", "3c321eee33013b289ab8775449df7df2"), + FANMADE("Jiggy Jiggy Uh! Uh!", "bc331588a71e7a1c8840f6cc9b9487e4"), + FANMADE("Jimmy In: The Alien Attack (v0.1)", "a4e9db0564a494728de7873684a4307c"), + FANMADE("Joe McMuffin In \"What's Cooking, Doc\" (v1.0)", "8a3de7e61a99cb605fa6d233dd91c8e1"), + FANMADE_LVF("Jolimie, le Village Maudit (v0.5)", "21818501636b3cb8ad5de5c1a66de5c2", Common::FR_FRA, 0x2936, GF_AGIMOUSE|GF_AGIPAL), + FANMADE_LVF("Jolimie, le Village Maudit (v1.1)", "68d7aef1161bb5972fe03efdf29ccb7f", Common::FR_FRA, 0x2936, GF_AGIMOUSE|GF_AGIPAL), + FANMADE("Journey Of Chef", "aa0a0b5a6364801ae65fdb96d6741df5"), + FANMADE("Jukebox (v1.0)", "c4b9c5528cc67f6ba777033830de7751"), + FANMADE("Justin Quest (v1.0 in development)", "103050989da7e0ffdc1c5e1793a4e1ec"), + FANMADE("J\xf5ulumaa (v0.05) (Estonian)", "53982ecbfb907e41392b3961ad1c3475"), + FANMADE("Kings Quest 2 - Breast Intentions (v2.0 Mar 26)", "a25d7379d281b1b296d4785df90a8e78"), + FANMADE("Kings Quest 2 - Breast Intentions (v2.0 Aug 16)", "6b4f796d0421d2e12e501b511962e03a"), + FANMADE("Lasse Holm: The Quest for Revenge (v1.0)", "f9fbcc8a4ef510bfbb92423296ff4abb"), + FANMADE("Lawman for Hire", "c78b28bfd3767dd455b992cd8b7854fa"), + FANMADE("Lefty Goes on Vacation (Not in The Right Place)", "ccdc49a33870310b01f2c48b8a1f3c34"), + FANMADE("Les Ins\xe3parables (v1.0)", "4b780887cab0ecabc5eca319acb3acf2"), + FANMADE("Little Pirate (Demo 2 v0.6)", "437068efe4ec32d436da09d6f2ea56e1"), + FANMADE("Lost Eternity (v1.0)", "95f15c5632feb8a39e9ca3d9af35fcc9"), + FANMADE("MD Quest - The Search for Michiel (v0.10)", "2a6fcb21d2b5e4144c38ed817fabe8ee"), + FANMADE("Maale Adummin Quest", "ddfbeb33feb7cf78504fe4dba14ec63b"), + FANMADE("Monkey Man", "2322d03f997e8cc235d4578efff69cfa"), + FANMADE_F("Napalm Quest (v0.5)", "b659afb491d967bb34810d1c6ce22093", GF_AGIMOUSE), + FANMADE("Naturette 1 (English v1.2)", "0a75884e7f010974a230bdf269651117"), + FANMADE("Naturette 1 (English v1.3)", "f15bbf999ac55ebd404aa1eb84f7c1d9"), + FANMADE_L("Naturette 1 (French v1.2)", "d3665622cc41aeb9c7ecf4fa43f20e53", Common::FR_FRA), + FANMADE_F("Naturette 2: Daughter of the Moon (v1.0)", "bdf76a45621c7f56d1c9d40292c6137a", GF_AGIMOUSE|GF_AGIPAL), + FANMADE_F("Naturette 3: Adventure in Treeworld (v1.0a)", "6dbb0e7fc75fec442e6d9e5a06f1530e", GF_AGIMOUSE|GF_AGIPAL), + FANMADE_F("Naturette 4: From a Planet to Another Planet (Not Finished)", "13be8cd9cf35aeff0a39b8757057fbc8", GF_AGIMOUSE), + // FIXME: Actually Naturette 4 has both English and French language support built into it. How to add that information? + FANMADE_F("Naturette 4: From a Planet to Another Planet (2007-10-05)", "8253706b6ef5423a79413b216760297c", GF_AGIMOUSE|GF_AGIPAL), + FANMADE("New AGI Hangman Test", "d69c0e9050ccc29fd662b74d9fc73a15"), + FANMADE("Nick's Quest - In Pursuit of QuakeMovie (v2.1 Gold)", "e29cbf9222551aee40397fabc83eeca0"), + FANMADE_F("Open Mic Night (v0.1)", "70000a2f67aac27d1133d019df70246d", GF_AGIMOUSE|GF_AGIPAL), + FANMADE("Operation: Recon", "0679ce8405411866ccffc8a6743370d0"), + FANMADE("Patrick's Quest (Demo v1.0)", "f254f5b894b98fec5f92acc07fb62841"), + FANMADE("Phantasmagoria", "87d20c1c11aee99a4baad3797b63146b"), + FANMADE("Pharaoh Quest (v0.0)", "51c630899d076cf799e573dadaa2276d"), + FANMADE("Phil's Quest - the Search for Tolbaga", "5e7ca45c360e03164b8358e49900c588"), + FANMADE("Pinkun Maze Quest (v0.1)", "148ff0843af389928b3939f463bfd20d"), + FANMADE("Pirate Quest", "bb612a919ed2b9ea23bbf03ce69fed42"), + FANMADE("Pothead (v0.1)", "d181101385d3a45082f418cd4b3c5b01"), + FANMADE("President's Quest", "4937d0e8ecadb7888faeb347799b0388"), + FANMADE("Prince Quest", "266248d75c3130c8ccc9c9bf2ad30a0d"), + FANMADE("Professor (English) - The Professor is Missing (Mar 17)", "6232de31cc204affdf2e92dfe3dc0e4d"), + FANMADE("Professor (English) - The Professor is Missing (Mar 22)", "b5fcf0ca2f0d1c073be82f01e2170961"), + FANMADE_L("Professor (French) - Le Professeur a Disparu", "7d9f8a4d4610bb9b0b97caa17590c2d3", Common::FR_FRA), + FANMADE("Quest for Glory VI - Hero's Adventure", "d26765c3075064c80d284c5e06e33a7e"), + FANMADE("Quest for Home", "d2895dc1cd3930f2489af0f843b144b3"), + FANMADE("Quest for Ladies (demo v1.1 Apr 1)", "3f6e02f16e1154a0daf296c8895edd97"), + FANMADE("Quest for Ladies (demo v1.1 Apr 6)", "f75e7b6a0769a3fa926eea0854711591"), + FANMADE("Quest for Piracy 1 - Enter the Silver Pirate (v0.15)", "d23f5c2a26f6dc60c686f8a2436ea4a6"), + FANMADE("Quest for a Record Deal", "f4fbd7abf056d2d3204f790da5ac89ab"), + FANMADE("Ralph's Quest (v0.1)", "5cf56378aa01a26ec30f25295f0750ca"), + FANMADE("Residence 44 Quest (Dutch v0.99)", "7c5cc64200660c70240053b33d379d7d"), + FANMADE("Residence 44 Quest (English v0.99)", "fe507851fddc863d540f2bec67cc67fd"), + FANMADE("Residence 44 Quest (English v1.0a)", "f99e3f69dc8c77a45399da9472ef5801"), + FANMADE("SQ2Eye (v0.3)", "2be2519401d38ad9ce8f43b948d093a3"), + // FANMADE("SQ2Eye (v0.4)", "2be2519401d38ad9ce8f43b948d093a3"), + FANMADE("SQ2Eye (v0.41)", "f0e82c55f10eb3542d7cd96c107ae113"), + FANMADE("SQ2Eye (v0.42)", "d7beae55f6328ef8b2da47b1aafea40c"), + FANMADE("SQ2Eye (v0.43)", "2a895f06e45de153bb4b77c982009e06"), + FANMADE("SQ2Eye (v0.44)", "5174fc4b6d8a477ba0ff0575cd64e0aa"), + FANMADE("SQ2Eye (v0.45)", "6e06f8bb7b90ce6f6aabf1a0e620159c"), + FANMADE("SQ2Eye (v0.46)", "bf0ad7a035ff9113951d09d1efe380c4"), + FANMADE("SQ2Eye (v0.47)", "85dc3be1d33ff932c292b74f9037abaa"), + FANMADE("SQ2Eye (v0.48)", "587574252972a5b5c070a647973a9b4a"), + FANMADE("SQ2Eye (v0.481)", "fc9234beb49804ae869696ce5af8ef30"), + FANMADE("SQ2Eye (v0.482)", "3ed84b7b87fa6840f25c15f250a11ffb"), + FANMADE("SQ2Eye (v0.483)", "647c31298d3f9cda641231b893e347c0"), + FANMADE("SQ2Eye (v0.484)", "f2c86fae7b9046d408c62c8c49a4b882"), + FANMADE("SQ2Eye (v0.485)", "af59e36bc28f44545458b68a93e91e67"), + FANMADE("SQ2Eye (v0.486)", "3fd86436e93456770dbdd4593eded70a"), + FANMADE("Save Santa (v1.0)", "4644f6beb5802081772f14be56ae196c"), + FANMADE("Save Santa (v1.3)", "f8afdb6efc5af5e7c0228b44633066af"), + FANMADE("Schiller (preview 1)", "ade39dea968c959cfebe1cf935d653e9"), + FANMADE("Schiller (preview 2)", "62cd1f8fc758bf6b4aa334e553624cef"), + GAME_F("serguei1", "v1.0", "b86725f067e456e10cdbdf5f58e01dec", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE), + // FIXME: The following two entries have identical MD5 checksums? + GAME_F("serguei1", "v1.1 2002 Sep 5", "91975c1fb4b13b0f9a8e9ff74731030d", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE), + GAME_F("serguei1", "v1.1 2003 Apr 10", "91975c1fb4b13b0f9a8e9ff74731030d", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE), + GAME_F("serguei2", "v0.1.1 Demo", "906ccbc2ddedb29b63141acc6d10cd28", 0x2917, GF_FANMADE|GF_AGIMOUSE, GID_FANMADE), + GAME_F("serguei2", "v1.3.1 Demo (March 22nd 2008)", "ad1308fcb8f48723cd388e012ebf5e20", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE), + FANMADE("Shifty (v1.0)", "2a07984d27b938364bf6bd243ac75080"), + FANMADE_F("Sliding Tile Game (v1.00)", "949bfff5d8a81c3139152eed4d84ca75", GF_AGIMOUSE), + FANMADE("Snowboarding Demo (v1.0)", "24bb8f29f1eddb5c0a099705267c86e4"), + FANMADE("Solar System Tour", "b5a3d0f392dfd76a6aa63f3d5f578403"), + FANMADE("Sorceror's Appraisal", "fe62615557b3cb7b08dd60c9d35efef1"), + GAME("sq0", "v1.03", "d2fd6f7404e86182458494e64375e590", 0x2917, GID_FANMADE), + GAME("sq0", "v1.04", "2ad9d1a4624a98571ee77dcc83f231b6", 0x2917, GID_FANMADE), + GAME_PS("sq0", "", "e1a8e4efcce86e1efcaa14633b9eb986", 762, 0x2440, GID_FANMADE, Common::kPlatformCoCo3), + GAME("sqx", "v10.0 Feb 05", "c992ae2f8ab18360404efdf16fa9edd1", 0x2917, GID_FANMADE), + GAME("sqx", "v10.0 Jul 18", "812edec45cefad559d190ffde2f9c910", 0x2917, GID_FANMADE), + GAME_PS("sqx", "", "f0a59044475a5fa37c055d8c3eb4d1a7", 768, 0x2440, GID_FANMADE, Common::kPlatformCoCo3), + FANMADE_F("Space Quest 3.5", "c077bc28d7b36213dd99dc9ecb0147fc", GF_AGIMOUSE|GF_AGIPAL), + FANMADE_F("Space Trek (v1.0)", "807a1aeadb2ace6968831d36ab5ea37a", GF_CLIPCOORDS), + FANMADE("Special Delivery", "88764dfe61126b8e73612c851b510a33"), + FANMADE("Speeder Bike Challenge (v1.0)", "2deb25bab379285ca955df398d96c1e7"), + FANMADE("Star Commander 1 - The Escape (v1.0)", "a7806f01e6fa14ebc029faa58f263750"), + FANMADE("Star Pilot: Bigger Fish", "8cb26f8e1c045b75c6576c839d4a0172"), + FANMADE_F("Street Quest (Demo)", "cf2aa94a7eb78dce6892c37f03e310d6", GF_AGIPAL), + FANMADE("Tales of the Tiki", "8103c9c87e3964690a14a3d0d83f7ddc"), + FANMADE("Tex McPhilip 1 - Quest For The Papacy", "3c74b9a24b51aa8020ac82bee3132266"), + FANMADE("Tex McPhilip 2 - Road To Divinity (v1.5)", "7387e8df854440bc26620ca0ea43af9a"), + FANMADE("Tex McPhilip 3 - A Destiny of Sin (Demo v0.25)", "992d12031a486ad84e592ff5d7c9d782"), + FANMADE("The 13th Disciple (v1.00)", "887719ad59afce9a41ec057dbb73ad73"), + FANMADE("The Adventures of a Crazed Hermit", "6e3086cbb794d3299a9c5a9792295511"), + FANMADE("The Grateful Dead", "c2146631afacf8cb455ce24f3d2d46e7"), + FANMADE("The Legend of Shay-Larah 1 - The Lost Prince", "04e720c8e30c9cf12db22ea14a24a3dd"), + FANMADE("The Legend of Zelda: The Fungus of Time (Demo v1.00)", "dcaf8166ceb62a3d9b9aea7f3b197c09"), + FANMADE("The Legendary Harry Soupsmith (Demo 1998 Apr 2)", "64c46b0d6fc135c9835afa80980d2831"), + FANMADE("The Legendary Harry Soupsmith (Demo 1998 Aug 19)", "8d06d82970f2c591d880a95476efbcf0"), + FANMADE("The Long Haired Dude: Encounter of the 18-th Kind", "86ea17b9fc2f3e537a7e40863d352c29"), + FANMADE("The Lost Planet (v0.9)", "590dffcbd932a9fbe554be13b769cac0"), + FANMADE("The Lost Planet (v1.0)", "58564df8b6394612dd4b6f5c0fd68d44"), + FANMADE("The New Adventure of Roger Wilco (v1.00)", "e5f0a7cb8d49f66b89114951888ca688"), + FANMADE("The Ruby Cast (v0.02)", "ed138e461bb1516e097007e017ab62df"), + FANMADE("The Shadow Plan", "c02cd10267e721f4e836b1431f504a0a"), + FANMADE("Time Quest (Demo v0.1)", "12e1a6f03ea4b8c5531acd0400b4ed8d"), + FANMADE("Time Quest (Demo v0.2)", "7b710608abc99e0861ac59b967bf3f6d"), + FANMADE_SVP("Time Quest", "90314f473d8317be5cd1f0306f139aea", 300, 0x2440, Common::kPlatformCoCo3), + FANMADE("Tonight The Shrieking Corpses Bleed (Demo v0.11)", "bcc57a7c8d563fa0c333107ae1c0a6e6"), + FANMADE("Tonight The Shrieking Corpses Bleed (v1.01)", "36b38f621b38e8d104aa0807302dc8c9"), + FANMADE("Turks' Quest - Heir to the Planet", "3d19254b737c8b218e5bc4580542b79a"), + FANMADE("URI Quest (v0.173 Feb 27)", "3986eefcf546dafc45f920ae91a697c3"), + FANMADE("URI Quest (v0.173 Jan 29)", "494150940d34130605a4f2e67ee40b12"), + { + // V - The Graphical Adventure + { + "agi-fanmade", + "V - The Graphical Adventure (Demo 2)", + AD_ENTRY1s("vdir", "c71f5c1e008d352ae9040b77fcf79327", 3080), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_USEEXTRAASTITLE, + GUIO_NONE + }, + GID_FANMADE, + GType_V3, + GF_FANMADE, + 0x3149, + }, + FANMADE_SVP("V - The Graphical Adventure", "1646eaade74f137a9041eb427a389969", 768, 0x2440, Common::kPlatformCoCo3), + + FANMADE("Voodoo Girl - Queen of the Darned (v1.2 2002 Jan 1)", "ae95f0c77d9a97b61420fd192348b937"), + FANMADE("Voodoo Girl - Queen of the Darned (v1.2 2002 Mar 29)", "11d0417b7b886f963d0b36789dac4c8f"), + FANMADE("Wizaro (v0.1)", "abeec1eda6eaf8dbc52443ea97ff140c"), + + { AD_TABLE_END_MARKER, 0, 0, 0, 0 } +}; + +/** + * The fallback game descriptor used by the AGI engine's fallbackDetector. + * Contents of this struct are to be overwritten by the fallbackDetector. + */ +static AGIGameDescription g_fallbackDesc = { + { + "", + "", + AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor + Common::UNK_LANG, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_FANMADE, + GType_V2, + GF_FANMADE, + 0x2917, +}; + +} // End of namespace Agi diff --git a/engines/agi/keyboard.cpp b/engines/agi/keyboard.cpp index 2bea49a807..62bcd5d8d8 100644 --- a/engines/agi/keyboard.cpp +++ b/engines/agi/keyboard.cpp @@ -104,10 +104,10 @@ int AgiEngine::handleController(int key) { VtEntry *v = &_game.viewTable[0]; int i; - // AGI 3.149 games and The Black Cauldron need KEY_ESCAPE to use menus + // AGI 3.149 games, The Black Cauldron and King's Quest 4 need KEY_ESCAPE to use menus // Games with the GF_ESCPAUSE flag need KEY_ESCAPE to pause the game if (key == 0 || - (key == KEY_ESCAPE && getVersion() != 0x3149 && getGameID() != GID_BC && !(getFeatures() & GF_ESCPAUSE)) ) + (key == KEY_ESCAPE && getVersion() != 0x3149 && getGameID() != GID_BC && getGameID() != GID_KQ4 && !(getFeatures() & GF_ESCPAUSE)) ) return false; if ((getGameID() == GID_MH1 || getGameID() == GID_MH2) && (key == KEY_ENTER) && @@ -121,7 +121,7 @@ int AgiEngine::handleController(int key) { if (_game.controllers[i].keycode == key) { debugC(3, kDebugLevelInput, "event %d: key press", _game.controllers[i].controller); _game.controllerOccured[_game.controllers[i].controller] = true; - report("event AC:%i occured\n", _game.controllers[i].controller); + report("event AC:%i occurred\n", _game.controllers[i].controller); return true; } } @@ -191,9 +191,8 @@ int AgiEngine::handleController(int key) { } } - v->flags &= ~ADJ_EGO_XY; - if (d || key == KEY_STATIONARY) { + v->flags &= ~ADJ_EGO_XY; v->direction = v->direction == d ? 0 : d; return true; } @@ -320,7 +319,7 @@ void AgiEngine::handleKeys(int key) { // Clear to start a new line _game.hasPrompt = 0; _game.inputBuffer[_game.cursorPos = 0] = 0; - debugC(3, kDebugLevelInput, "clear lines"); + debugC(3, kDebugLevelInput | kDebugLevelText, "clear lines"); clearLines(l, l + 1, bg); flushLines(l, l + 1); #ifdef __DS__ diff --git a/engines/agi/loader_v2.cpp b/engines/agi/loader_v2.cpp index 3d1c4fa2cf..de6f8d0653 100644 --- a/engines/agi/loader_v2.cpp +++ b/engines/agi/loader_v2.cpp @@ -232,7 +232,7 @@ int AgiLoader_v2::loadResource(int t, int n) { if (data != NULL) { // Freeing of the raw resource from memory is delegated to the createFromRawResource-function - _vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound); + _vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound, _vm->_soundemu); _vm->_game.dirSound[n].flags |= RES_LOADED; } else { ec = errBadResource; diff --git a/engines/agi/loader_v3.cpp b/engines/agi/loader_v3.cpp index cd97c44521..f145140768 100644 --- a/engines/agi/loader_v3.cpp +++ b/engines/agi/loader_v3.cpp @@ -227,19 +227,12 @@ uint8 *AgiLoader_v3::loadVolRes(AgiDir *agid) { compBuffer = (uint8 *)calloc(1, agid->clen + 32); fp.read(compBuffer, agid->clen); - if (x[2] & 0x80 || agid->len == agid->clen) { + if (x[2] & 0x80) { // compressed pic + data = _vm->_picture->convertV3Pic(compBuffer, agid->clen); + // compBuffer has been freed inside convertV3Pic() + } else if (agid->len == agid->clen) { // do not decompress data = compBuffer; - -#if 0 - // CM: added to avoid problems in - // convert_v2_v3_pic() when clen > len - // e.g. Sierra demo 4, first picture - // (Tue Mar 16 13:13:43 EST 1999) - agid->len = agid->clen; - - // Now removed to fix Gold Rush! in demo4 -#endif } else { // it is compressed data = (uint8 *)calloc(1, agid->len + 32); @@ -309,7 +302,6 @@ int AgiLoader_v3::loadResource(int t, int n) { unloadResource(rPICTURE, n); data = loadVolRes(&_vm->_game.dirPic[n]); if (data != NULL) { - data = _vm->_picture->convertV3Pic(data, _vm->_game.dirPic[n].len); _vm->_game.pictures[n].rdata = data; _vm->_game.dirPic[n].flags |= RES_LOADED; } else { @@ -324,7 +316,7 @@ int AgiLoader_v3::loadResource(int t, int n) { data = loadVolRes(&_vm->_game.dirSound[n]); if (data != NULL) { // Freeing of the raw resource from memory is delegated to the createFromRawResource-function - _vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound); + _vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound, _vm->_soundemu); _vm->_game.dirSound[n].flags |= RES_LOADED; } else { ec = errBadResource; diff --git a/engines/agi/module.mk b/engines/agi/module.mk index f031834c9d..2339d1019f 100644 --- a/engines/agi/module.mk +++ b/engines/agi/module.mk @@ -30,6 +30,11 @@ MODULE_OBJS := \ predictive.o \ saveload.o \ sound.o \ + sound_2gs.o \ + sound_coco3.o \ + sound_midi.o \ + sound_pcjr.o \ + sound_sarien.o \ sprite.o \ text.o \ view.o \ diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp index d7e3ba416c..072ab0114f 100644 --- a/engines/agi/op_cmd.cpp +++ b/engines/agi/op_cmd.cpp @@ -43,221 +43,201 @@ namespace Agi { #define p5 (p[5]) #define p6 (p[6]) -#define game g_agi->_game -#define g_sprites g_agi->_sprites -#define g_sound g_agi->_sound -#define g_gfx g_agi->_gfx -#define g_picture g_agi->_picture +#define ip _curLogic->cIP +#define vt _game.viewTable[p0] +#define vt_v _game.viewTable[_game.vars[p0]] -#define ip curLogic->cIP -#define vt game.viewTable[p0] -#define vt_v game.viewTable[game.vars[p0]] +#define _v _game.vars -static struct AgiLogic *curLogic; - -int timerHack; // Workaround for timer loop in MH1 - -#define _v game.vars -#define cmd(x) static void cmd_##x (AgiEngine *g_agi, uint8 *p) - -cmd(increment) { +void AgiEngine::cmd_increment(uint8 *p) { if (_v[p0] != 0xff) ++_v[p0]; } -cmd(decrement) { +void AgiEngine::cmd_decrement(uint8 *p) { if (_v[p0] != 0) --_v[p0]; } -cmd(assignn) { +void AgiEngine::cmd_assignn(uint8 *p) { _v[p0] = p1; - // WORKAROUND for a bug in fan game "Get outta SQ" + // WORKAROUND for a bug in fan _game "Get outta SQ" // Total number of points is stored in variable 7, which - // is then incorrectly assigned to 0. Thus, when the game + // is then incorrectly assigned to 0. Thus, when the _game // is restarted, "Points 0 of 0" is shown. We set the // variable to the correct value here // Fixes bug #1942476 - "AGI: Fan(Get Outta SQ) - Score // is lost on restart" - if (g_agi->getGameID() == GID_GETOUTTASQ && p0 == 7) + if (getGameID() == GID_GETOUTTASQ && p0 == 7) _v[p0] = 8; } -cmd(addn) { +void AgiEngine::cmd_addn(uint8 *p) { _v[p0] += p1; } -cmd(subn) { +void AgiEngine::cmd_subn(uint8 *p) { _v[p0] -= p1; } -cmd(assignv) { +void AgiEngine::cmd_assignv(uint8 *p) { _v[p0] = _v[p1]; } -cmd(addv) { +void AgiEngine::cmd_addv(uint8 *p) { _v[p0] += _v[p1]; } -cmd(subv) { +void AgiEngine::cmd_subv(uint8 *p) { _v[p0] -= _v[p1]; } -cmd(mul_n) { +void AgiEngine::cmd_mul_n(uint8 *p) { _v[p0] *= p1; } -cmd(mul_v) { +void AgiEngine::cmd_mul_v(uint8 *p) { _v[p0] *= _v[p1]; } -cmd(div_n) { +void AgiEngine::cmd_div_n(uint8 *p) { _v[p0] /= p1; } -cmd(div_v) { +void AgiEngine::cmd_div_v(uint8 *p) { _v[p0] /= _v[p1]; } -cmd(random) { - _v[p2] = g_agi->_rnd->getRandomNumber(p1 - p0) + p0; +void AgiEngine::cmd_random(uint8 *p) { + _v[p2] = _rnd->getRandomNumber(p1 - p0) + p0; } -cmd(lindirectn) { +void AgiEngine::cmd_lindirectn(uint8 *p) { _v[_v[p0]] = p1; } -cmd(lindirectv) { +void AgiEngine::cmd_lindirectv(uint8 *p) { _v[_v[p0]] = _v[p1]; } -cmd(rindirect) { +void AgiEngine::cmd_rindirect(uint8 *p) { _v[p0] = _v[_v[p1]]; } -cmd(set) { - g_agi->setflag(*p, true); +void AgiEngine::cmd_set(uint8 *p) { + setflag(*p, true); } -cmd(reset) { - g_agi->setflag(*p, false); +void AgiEngine::cmd_reset(uint8 *p) { + setflag(*p, false); } -cmd(toggle) { - g_agi->setflag(*p, !g_agi->getflag(*p)); +void AgiEngine::cmd_toggle(uint8 *p) { + setflag(*p, !getflag(*p)); } -cmd(set_v) { - g_agi->setflag(_v[p0], true); +void AgiEngine::cmd_set_v(uint8 *p) { + setflag(_v[p0], true); } -cmd(reset_v) { - g_agi->setflag(_v[p0], false); +void AgiEngine::cmd_reset_v(uint8 *p) { + setflag(_v[p0], false); } -cmd(toggle_v) { - g_agi->setflag(_v[p0], !g_agi->getflag(_v[p0])); +void AgiEngine::cmd_toggle_v(uint8 *p) { + setflag(_v[p0], !getflag(_v[p0])); } -cmd(new_room) { - g_agi->newRoom(p0); +void AgiEngine::cmd_new_room(uint8 *p) { + newRoom(p0); // WORKAROUND: Works around intro skipping bug (#1737343) in Gold Rush. // Intro was skipped because the enter-keypress finalizing the entering // of the copy protection string (Copy protection is in logic.128) was // left over to the intro scene (Starts with room 73 i.e. logic.073). // The intro scene checks for any keys pressed and if it finds any it - // jumps to the game's start (Room 1 i.e. logic.001). We clear the + // jumps to the _game's start (Room 1 i.e. logic.001). We clear the // keyboard buffer when the intro sequence's first room (Room 73) is // loaded so that no keys from the copy protection scene can be left - // over to cause the intro to skip to the game's start. - if (g_agi->getGameID() == GID_GOLDRUSH && p0 == 73) - game.keypress = 0; + // over to cause the intro to skip to the _game's start. + if (getGameID() == GID_GOLDRUSH && p0 == 73) + _game.keypress = 0; } -cmd(new_room_f) { - g_agi->newRoom(_v[p0]); +void AgiEngine::cmd_new_room_f(uint8 *p) { + newRoom(_v[p0]); } -cmd(load_view) { - g_agi->agiLoadResource(rVIEW, p0); +void AgiEngine::cmd_load_view(uint8 *p) { + agiLoadResource(rVIEW, p0); } -cmd(load_logic) { - g_agi->agiLoadResource(rLOGIC, p0); +void AgiEngine::cmd_load_logic(uint8 *p) { + agiLoadResource(rLOGIC, p0); } -cmd(load_sound) { - g_agi->agiLoadResource(rSOUND, p0); +void AgiEngine::cmd_load_sound(uint8 *p) { + agiLoadResource(rSOUND, p0); } -cmd(load_view_f) { - g_agi->agiLoadResource(rVIEW, _v[p0]); +void AgiEngine::cmd_load_view_f(uint8 *p) { + agiLoadResource(rVIEW, _v[p0]); } -cmd(load_logic_f) { - g_agi->agiLoadResource(rLOGIC, _v[p0]); +void AgiEngine::cmd_load_logic_f(uint8 *p) { + agiLoadResource(rLOGIC, _v[p0]); } -cmd(discard_view) { - g_agi->agiUnloadResource(rVIEW, p0); +void AgiEngine::cmd_discard_view(uint8 *p) { + agiUnloadResource(rVIEW, p0); } -cmd(object_on_anything) { +void AgiEngine::cmd_object_on_anything(uint8 *p) { vt.flags &= ~(ON_WATER | ON_LAND); } -cmd(object_on_land) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); +void AgiEngine::cmd_object_on_land(uint8 *p) { vt.flags |= ON_LAND; } -cmd(object_on_water) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); +void AgiEngine::cmd_object_on_water(uint8 *p) { vt.flags |= ON_WATER; } -cmd(observe_horizon) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); +void AgiEngine::cmd_observe_horizon(uint8 *p) { vt.flags &= ~IGNORE_HORIZON; } -cmd(ignore_horizon) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); +void AgiEngine::cmd_ignore_horizon(uint8 *p) { vt.flags |= IGNORE_HORIZON; } -cmd(observe_objs) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); +void AgiEngine::cmd_observe_objs(uint8 *p) { vt.flags &= ~IGNORE_OBJECTS; } -cmd(ignore_objs) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); +void AgiEngine::cmd_ignore_objs(uint8 *p) { vt.flags |= IGNORE_OBJECTS; } -cmd(observe_blocks) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); +void AgiEngine::cmd_observe_blocks(uint8 *p) { vt.flags &= ~IGNORE_BLOCKS; } -cmd(ignore_blocks) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); +void AgiEngine::cmd_ignore_blocks(uint8 *p) { vt.flags |= IGNORE_BLOCKS; } -cmd(set_horizon) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); - game.horizon = p0; +void AgiEngine::cmd_set_horizon(uint8 *p) { + _game.horizon = p0; } -cmd(get_priority) { +void AgiEngine::cmd_get_priority(uint8 *p) { _v[p1] = vt.priority; } -cmd(set_priority) { +void AgiEngine::cmd_set_priority(uint8 *p) { vt.flags |= FIXED_PRIORITY; vt.priority = p1; @@ -268,259 +248,256 @@ cmd(set_priority) { // It seems that in this scene, ego's priority is set to 8, but the priority of // the last dwarf with the soup bowls (view 152) is also set to 8, which causes // the dwarf to be drawn behind ego - // With this workaround, when the game scripts set the priority of view 152 + // With this workaround, when the _game scripts set the priority of view 152 // (seventh dwarf with soup bowls), ego's priority is set to 7 - // The game script itself sets priotity 8 for ego before she starts walking, + // The _game script itself sets priotity 8 for ego before she starts walking, // and then releases the fixed priority set on ego after ego is seated // Therefore, this workaround only affects that specific part of this scene // Ego is set to object 19 by script 54 - if (g_agi->getGameID() == GID_KQ4 && vt.currentView == 152) { - game.viewTable[19].flags |= FIXED_PRIORITY; - game.viewTable[19].priority = 7; + if (getGameID() == GID_KQ4 && vt.currentView == 152) { + _game.viewTable[19].flags |= FIXED_PRIORITY; + _game.viewTable[19].priority = 7; } } -cmd(set_priority_f) { +void AgiEngine::cmd_set_priority_f(uint8 *p) { vt.flags |= FIXED_PRIORITY; vt.priority = _v[p1]; } -cmd(release_priority) { +void AgiEngine::cmd_release_priority(uint8 *p) { vt.flags &= ~FIXED_PRIORITY; } -cmd(set_upper_left) { // do nothing (AGI 2.917) +void AgiEngine::cmd_set_upper_left(uint8 *p) { // do nothing (AGI 2.917) } -cmd(start_update) { - g_agi->startUpdate(&vt); +void AgiEngine::cmd_start_update(uint8 *p) { + startUpdate(&vt); } -cmd(stop_update) { - g_agi->stopUpdate(&vt); +void AgiEngine::cmd_stop_update(uint8 *p) { + stopUpdate(&vt); } -cmd(current_view) { +void AgiEngine::cmd_current_view(uint8 *p) { _v[p1] = vt.currentView; } -cmd(current_cel) { +void AgiEngine::cmd_current_cel(uint8 *p) { _v[p1] = vt.currentCel; debugC(4, kDebugLevelScripts, "v%d=%d", p1, _v[p1]); } -cmd(current_loop) { +void AgiEngine::cmd_current_loop(uint8 *p) { _v[p1] = vt.currentLoop; } -cmd(last_cel) { +void AgiEngine::cmd_last_cel(uint8 *p) { _v[p1] = vt.loopData->numCels - 1; } -cmd(set_cel) { - g_agi->setCel(&vt, p1); +void AgiEngine::cmd_set_cel(uint8 *p) { + setCel(&vt, p1); vt.flags &= ~DONTUPDATE; } -cmd(set_cel_f) { - g_agi->setCel(&vt, _v[p1]); +void AgiEngine::cmd_set_cel_f(uint8 *p) { + setCel(&vt, _v[p1]); vt.flags &= ~DONTUPDATE; } -cmd(set_view) { - debugC(4, kDebugLevelScripts, "o%d, %d", p0, p1); - g_agi->setView(&vt, p1); +void AgiEngine::cmd_set_view(uint8 *p) { + setView(&vt, p1); } -cmd(set_view_f) { - g_agi->setView(&vt, _v[p1]); +void AgiEngine::cmd_set_view_f(uint8 *p) { + setView(&vt, _v[p1]); } -cmd(set_loop) { - g_agi->setLoop(&vt, p1); +void AgiEngine::cmd_set_loop(uint8 *p) { + setLoop(&vt, p1); } -cmd(set_loop_f) { - g_agi->setLoop(&vt, _v[p1]); +void AgiEngine::cmd_set_loop_f(uint8 *p) { + setLoop(&vt, _v[p1]); } -cmd(number_of_loops) { +void AgiEngine::cmd_number_of_loops(uint8 *p) { _v[p1] = vt.numLoops; } -cmd(fix_loop) { +void AgiEngine::cmd_fix_loop(uint8 *p) { vt.flags |= FIX_LOOP; } -cmd(release_loop) { +void AgiEngine::cmd_release_loop(uint8 *p) { vt.flags &= ~FIX_LOOP; } -cmd(step_size) { +void AgiEngine::cmd_step_size(uint8 *p) { vt.stepSize = _v[p1]; } -cmd(step_time) { +void AgiEngine::cmd_step_time(uint8 *p) { vt.stepTime = vt.stepTimeCount = _v[p1]; } -cmd(cycle_time) { +void AgiEngine::cmd_cycle_time(uint8 *p) { vt.cycleTime = vt.cycleTimeCount = _v[p1]; } -cmd(stop_cycling) { +void AgiEngine::cmd_stop_cycling(uint8 *p) { vt.flags &= ~CYCLING; } -cmd(start_cycling) { +void AgiEngine::cmd_start_cycling(uint8 *p) { vt.flags |= CYCLING; } -cmd(normal_cycle) { +void AgiEngine::cmd_normal_cycle(uint8 *p) { vt.cycle = CYCLE_NORMAL; vt.flags |= CYCLING; } -cmd(reverse_cycle) { +void AgiEngine::cmd_reverse_cycle(uint8 *p) { vt.cycle = CYCLE_REVERSE; vt.flags |= CYCLING; } -cmd(set_dir) { +void AgiEngine::cmd_set_dir(uint8 *p) { vt.direction = _v[p1]; } -cmd(get_dir) { +void AgiEngine::cmd_get_dir(uint8 *p) { _v[p1] = vt.direction; } -cmd(get_room_f) { - _v[p1] = g_agi->objectGetLocation(_v[p0]); +void AgiEngine::cmd_get_room_f(uint8 *p) { + _v[p1] = objectGetLocation(_v[p0]); } -cmd(put) { - g_agi->objectSetLocation(p0, _v[p1]); +void AgiEngine::cmd_put(uint8 *p) { + objectSetLocation(p0, _v[p1]); } -cmd(put_f) { - g_agi->objectSetLocation(_v[p0], _v[p1]); +void AgiEngine::cmd_put_f(uint8 *p) { + objectSetLocation(_v[p0], _v[p1]); } -cmd(drop) { - g_agi->objectSetLocation(p0, 0); +void AgiEngine::cmd_drop(uint8 *p) { + objectSetLocation(p0, 0); } -cmd(get) { - g_agi->objectSetLocation(p0, EGO_OWNED); +void AgiEngine::cmd_get(uint8 *p) { + objectSetLocation(p0, EGO_OWNED); } -cmd(get_f) { - g_agi->objectSetLocation(_v[p0], EGO_OWNED); +void AgiEngine::cmd_get_f(uint8 *p) { + objectSetLocation(_v[p0], EGO_OWNED); } -cmd(word_to_string) { - strcpy(game.strings[p0], game.egoWords[p1].word); +void AgiEngine::cmd_word_to_string(uint8 *p) { + strcpy(_game.strings[p0], _game.egoWords[p1].word); } -cmd(open_dialogue) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); - game.hasWindow = true; +void AgiEngine::cmd_open_dialogue(uint8 *p) { + _game.hasWindow = true; } -cmd(close_dialogue) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); - game.hasWindow = false; +void AgiEngine::cmd_close_dialogue(uint8 *p) { + _game.hasWindow = false; } -cmd(close_window) { - g_agi->closeWindow(); +void AgiEngine::cmd_close_window(uint8 *p) { + closeWindow(); } -cmd(status_line_on) { - game.statusLine = true; - g_agi->writeStatus(); +void AgiEngine::cmd_status_line_on(uint8 *p) { + _game.statusLine = true; + writeStatus(); } -cmd(status_line_off) { - game.statusLine = false; - g_agi->writeStatus(); +void AgiEngine::cmd_status_line_off(uint8 *p) { + _game.statusLine = false; + writeStatus(); } -cmd(show_obj) { - g_sprites->showObj(p0); +void AgiEngine::cmd_show_obj(uint8 *p) { + _sprites->showObj(p0); } -cmd(show_obj_v) { - g_sprites->showObj(_v[p0]); +void AgiEngine::cmd_show_obj_v(uint8 *p) { + _sprites->showObj(_v[p0]); } -cmd(sound) { - g_sound->startSound(p0, p1); +void AgiEngine::cmd_sound(uint8 *p) { + _sound->startSound(p0, p1); } -cmd(stop_sound) { - g_sound->stopSound(); +void AgiEngine::cmd_stop_sound(uint8 *p) { + _sound->stopSound(); } -cmd(menu_input) { - g_agi->newInputMode(INPUT_MENU); +void AgiEngine::cmd_menu_input(uint8 *p) { + newInputMode(INPUT_MENU); } -cmd(enable_item) { - g_agi->_menu->setItem(p0, true); +void AgiEngine::cmd_enable_item(uint8 *p) { + _menu->setItem(p0, true); } -cmd(disable_item) { - g_agi->_menu->setItem(p0, false); +void AgiEngine::cmd_disable_item(uint8 *p) { + _menu->setItem(p0, false); } -cmd(submit_menu) { - g_agi->_menu->submit(); +void AgiEngine::cmd_submit_menu(uint8 *p) { + _menu->submit(); } -cmd(set_scan_start) { - curLogic->sIP = curLogic->cIP; +void AgiEngine::cmd_set_scan_start(uint8 *p) { + _curLogic->sIP = _curLogic->cIP; } -cmd(reset_scan_start) { - curLogic->sIP = 2; +void AgiEngine::cmd_reset_scan_start(uint8 *p) { + _curLogic->sIP = 2; } -cmd(save_game) { - game.simpleSave ? g_agi->saveGameSimple() : g_agi->saveGameDialog(); +void AgiEngine::cmd_save_game(uint8 *p) { + _game.simpleSave ? saveGameSimple() : saveGameDialog(); } -cmd(load_game) { +void AgiEngine::cmd_load_game(uint8 *p) { assert(1); - game.simpleSave ? g_agi->loadGameSimple() : g_agi->loadGameDialog(); + _game.simpleSave ? loadGameSimple() : loadGameDialog(); } -cmd(init_disk) { // do nothing +void AgiEngine::cmd_init_disk(uint8 *p) { // do nothing } -cmd(log) { // do nothing +void AgiEngine::cmd_log(uint8 *p) { // do nothing } -cmd(trace_on) { // do nothing +void AgiEngine::cmd_trace_on(uint8 *p) { // do nothing } -cmd(trace_info) { // do nothing +void AgiEngine::cmd_trace_info(uint8 *p) { // do nothing } -cmd(show_mem) { - g_agi->messageBox("Enough memory"); +void AgiEngine::cmd_show_mem(uint8 *p) { + messageBox("Enough memory"); } -cmd(init_joy) { // do nothing +void AgiEngine::cmd_init_joy(uint8 *p) { // do nothing } -cmd(script_size) { +void AgiEngine::cmd_script_size(uint8 *p) { report("script.size(%d)\n", p0); } -cmd(cancel_line) { - g_agi->_game.inputBuffer[0] = 0; - g_agi->writePrompt(); +void AgiEngine::cmd_cancel_line(uint8 *p) { + _game.inputBuffer[0] = 0; + writePrompt(); } // This implementation is based on observations of Amiga's Gold Rush. @@ -533,7 +510,7 @@ cmd(cancel_line) { // 4051 (When ego is stationary), // 471 (When walking on the first screen's bridge), // 71 (When walking around, using the mouse or the keyboard). -cmd(obj_status_f) { +void AgiEngine::cmd_obj_status_f(uint8 *p) { const char *cycleDesc; // Object's cycle description line const char *motionDesc; // Object's motion description line char msg[256]; // The whole object status message @@ -594,7 +571,7 @@ cmd(obj_status_f) { vt_v.stepSize, cycleDesc, motionDesc); - g_agi->messageBox(msg); + messageBox(msg); } // unknown commands: @@ -605,49 +582,49 @@ cmd(obj_status_f) { // unk_174: Change priority table (used in KQ4) -- j5 // unk_177: Disable menus completely -- j5 // unk_181: Deactivate keypressed control (default control of ego) -cmd(set_simple) { - if (!(g_agi->getFeatures() & (GF_AGI256 | GF_AGI256_2))) { - game.simpleSave = true; +void AgiEngine::cmd_set_simple(uint8 *p) { + if (!(getFeatures() & (GF_AGI256 | GF_AGI256_2))) { + _game.simpleSave = true; } else { // AGI256 and AGI256-2 use this unknown170 command to load 256 color pictures. - // Load the picture. Similar to cmd(load_pic). - g_sprites->eraseBoth(); - g_agi->agiLoadResource(rPICTURE, _v[p0]); + // Load the picture. Similar to void AgiEngine::cmd_load_pic(uint8 *p). + _sprites->eraseBoth(); + agiLoadResource(rPICTURE, _v[p0]); - // Draw the picture. Similar to cmd(draw_pic). - g_picture->decodePicture(_v[p0], false, true); - g_sprites->blitBoth(); - game.pictureShown = 0; + // Draw the picture. Similar to void AgiEngine::cmd_draw_pic(uint8 *p). + _picture->decodePicture(_v[p0], false, true); + _sprites->blitBoth(); + _game.pictureShown = 0; - // Show the picture. Similar to cmd(show_pic). - g_agi->setflag(fOutputMode, false); - cmd_close_window(g_agi, NULL); - g_picture->showPic(); - game.pictureShown = 1; + // Show the picture. Similar to void AgiEngine::cmd_show_pic(uint8 *p). + setflag(fOutputMode, false); + closeWindow(); + _picture->showPic(); + _game.pictureShown = 1; // Simulate slowww computer. Many effects rely on this - g_agi->pause(kPausePicture); + pause(kPausePicture); } } -cmd(pop_script) { - if (g_agi->getVersion() >= 0x2915) { +void AgiEngine::cmd_pop_script(uint8 *p) { + if (getVersion() >= 0x2915) { report("pop.script\n"); } } -cmd(hold_key) { - if (g_agi->getVersion() >= 0x3098) { - g_agi->_egoHoldKey = true; +void AgiEngine::cmd_hold_key(uint8 *p) { + if (getVersion() >= 0x3098) { + _egoHoldKey = true; } } -cmd(discard_sound) { - if (g_agi->getVersion() >= 0x2936) { +void AgiEngine::cmd_discard_sound(uint8 *p) { + if (getVersion() >= 0x2936) { report("discard.sound\n"); } } -cmd(hide_mouse) { +void AgiEngine::cmd_hide_mouse(uint8 *p) { // WORKAROUND: Turns off current movement that's being caused with the mouse. // This fixes problems with too many popup boxes appearing in the Amiga // Gold Rush's copy protection failure scene (i.e. the hanging scene, logic.192). @@ -655,34 +632,34 @@ cmd(hide_mouse) { // to walk somewhere else than to the right using the mouse. // FIXME: Write a proper implementation using disassembly and // apply it to other games as well if applicable. - game.viewTable[0].flags &= ~ADJ_EGO_XY; + _game.viewTable[0].flags &= ~ADJ_EGO_XY; g_system->showMouse(false); } -cmd(allow_menu) { - if (g_agi->getVersion() >= 0x3098) { - g_agi->setflag(fMenusWork, ((p0 != 0) ? true : false)); +void AgiEngine::cmd_allow_menu(uint8 *p) { + if (getVersion() >= 0x3098) { + setflag(fMenusWork, ((p0 != 0) ? true : false)); } } -cmd(show_mouse) { +void AgiEngine::cmd_show_mouse(uint8 *p) { g_system->showMouse(true); } -cmd(fence_mouse) { - g_agi->_game.mouseFence.moveTo(p0, p1); - g_agi->_game.mouseFence.setWidth(p2 - p0); - g_agi->_game.mouseFence.setHeight(p3 - p1); +void AgiEngine::cmd_fence_mouse(uint8 *p) { + _game.mouseFence.moveTo(p0, p1); + _game.mouseFence.setWidth(p2 - p0); + _game.mouseFence.setHeight(p3 - p1); } -cmd(release_key) { - if (g_agi->getVersion() >= 0x3098) { - g_agi->_egoHoldKey = false; +void AgiEngine::cmd_release_key(uint8 *p) { + if (getVersion() >= 0x3098) { + _egoHoldKey = false; } } -cmd(adj_ego_move_to_x_y) { +void AgiEngine::cmd_adj_ego_move_to_x_y(uint8 *p) { int8 x, y; switch (logicNamesCmd[182].numArgs) { @@ -704,56 +681,57 @@ cmd(adj_ego_move_to_x_y) { // onto the ladder so this is more like it (Although that may be caused // by something else because this command doesn't do any flag manipulations // in the Amiga version - checked it with disassembly). - if (x != game.adjMouseX || y != game.adjMouseY) - game.viewTable[EGO_VIEW_TABLE].flags &= ~ADJ_EGO_XY; + if (x != _game.adjMouseX || y != _game.adjMouseY) + _game.viewTable[EGO_VIEW_TABLE].flags &= ~ADJ_EGO_XY; - game.adjMouseX = x; - game.adjMouseY = y; + _game.adjMouseX = x; + _game.adjMouseY = y; debugC(4, kDebugLevelScripts, "adj.ego.move.to.x.y(%d, %d)", x, y); break; // TODO: Check where (if anywhere) the 0 arguments version is used case 0: default: - game.viewTable[0].flags |= ADJ_EGO_XY; + _game.viewTable[0].flags |= ADJ_EGO_XY; break; } } -cmd(parse) { +void AgiEngine::cmd_parse(uint8 *p) { _v[vWordNotFound] = 0; - g_agi->setflag(fEnteredCli, false); - g_agi->setflag(fSaidAcceptedInput, false); + setflag(fEnteredCli, false); + setflag(fSaidAcceptedInput, false); - g_agi->dictionaryWords(g_agi->agiSprintf(game.strings[p0])); + dictionaryWords(agiSprintf(_game.strings[p0])); } -cmd(call) { +void AgiEngine::cmd_call(uint8 *p) { int oldCIP; int oldLognum; // CM: we don't save sIP because set.scan.start can be // used in a called script (fixes xmas demo) - oldCIP = curLogic->cIP; - oldLognum = game.lognum; + oldCIP = _curLogic->cIP; + oldLognum = _game.lognum; - g_agi->runLogic(p0); + runLogic(p0); - game.lognum = oldLognum; - curLogic = &game.logics[game.lognum]; - curLogic->cIP = oldCIP; + _game.lognum = oldLognum; + _curLogic = &_game.logics[_game.lognum]; + _curLogic->cIP = oldCIP; } -cmd(call_f) { - cmd_call(g_agi, &_v[p0]); +void AgiEngine::cmd_call_f(uint8 *p) { + cmd_call(&_v[p0]); } -cmd(draw_pic) { +void AgiEngine::cmd_draw_pic(uint8 *p) { debugC(6, kDebugLevelScripts, "=== draw pic %d ===", _v[p0]); - g_sprites->eraseBoth(); - g_picture->decodePicture(_v[p0], true); - g_sprites->blitBoth(); - game.pictureShown = 0; + _sprites->eraseBoth(); + _picture->decodePicture(_v[p0], true); + _sprites->blitBoth(); + _sprites->commitBoth(); + _game.pictureShown = 0; debugC(6, kDebugLevelScripts, "--- end of draw pic %d ---", _v[p0]); // WORKAROUND for a script bug which exists in SQ1, logic scripts @@ -768,63 +746,64 @@ cmd(draw_pic) { // above the ground), flag 103 is reset, thereby fixing this issue. Note // that this is a script bug and occurs in the original interpreter as well. // Fixes bug #1658514: AGI: SQ1 (2.2 DOS ENG) bizzare exploding roger - if (g_agi->getGameID() == GID_SQ1 && _v[p0] == 20) - g_agi->setflag(103, false); + if (getGameID() == GID_SQ1 && _v[p0] == 20) + setflag(103, false); // Simulate slowww computer. Many effects rely on this - g_agi->pause(kPausePicture); + pause(kPausePicture); } -cmd(show_pic) { +void AgiEngine::cmd_show_pic(uint8 *p) { debugC(6, kDebugLevelScripts, "=== show pic ==="); - g_agi->setflag(fOutputMode, false); - cmd_close_window(g_agi, NULL); - g_picture->showPic(); - game.pictureShown = 1; + setflag(fOutputMode, false); + closeWindow(); + _picture->showPic(); + _game.pictureShown = 1; debugC(6, kDebugLevelScripts, "--- end of show pic ---"); } -cmd(load_pic) { - g_sprites->eraseBoth(); - g_agi->agiLoadResource(rPICTURE, _v[p0]); - g_sprites->blitBoth(); +void AgiEngine::cmd_load_pic(uint8 *p) { + _sprites->eraseBoth(); + agiLoadResource(rPICTURE, _v[p0]); + _sprites->blitBoth(); + _sprites->commitBoth(); } -cmd(discard_pic) { +void AgiEngine::cmd_discard_pic(uint8 *p) { debugC(6, kDebugLevelScripts, "--- discard pic ---"); // do nothing } -cmd(overlay_pic) { +void AgiEngine::cmd_overlay_pic(uint8 *p) { debugC(6, kDebugLevelScripts, "--- overlay pic ---"); - g_sprites->eraseBoth(); - g_picture->decodePicture(_v[p0], false); - g_sprites->blitBoth(); - game.pictureShown = 0; - g_sprites->commitBoth(); + _sprites->eraseBoth(); + _picture->decodePicture(_v[p0], false); + _sprites->blitBoth(); + _game.pictureShown = 0; + _sprites->commitBoth(); // Simulate slowww computer. Many effects rely on this - g_agi->pause(kPausePicture); + pause(kPausePicture); } -cmd(show_pri_screen) { - g_agi->_debug.priority = 1; - g_sprites->eraseBoth(); - g_picture->showPic(); - g_sprites->blitBoth(); +void AgiEngine::cmd_show_pri_screen(uint8 *p) { + _debug.priority = 1; + _sprites->eraseBoth(); + _picture->showPic(); + _sprites->blitBoth(); - g_agi->waitKey(); + waitKey(); - g_agi->_debug.priority = 0; - g_sprites->eraseBoth(); - g_picture->showPic(); - g_sprites->blitBoth(); + _debug.priority = 0; + _sprites->eraseBoth(); + _picture->showPic(); + _sprites->blitBoth(); } -cmd(animate_obj) { +void AgiEngine::cmd_animate_obj(uint8 *p) { if (vt.flags & ANIMATED) return; @@ -835,14 +814,14 @@ cmd(animate_obj) { vt.direction = 0; } -cmd(unanimate_all) { +void AgiEngine::cmd_unanimate_all(uint8 *p) { int i; for (i = 0; i < MAX_VIEWTABLE; i++) - game.viewTable[i].flags &= ~(ANIMATED | DRAWN); + _game.viewTable[i].flags &= ~(ANIMATED | DRAWN); } -cmd(draw) { +void AgiEngine::cmd_draw(uint8 *p) { if (vt.flags & DRAWN) return; @@ -852,19 +831,19 @@ cmd(draw) { debugC(4, kDebugLevelScripts, "draw entry %d", vt.entry); vt.flags |= UPDATE; - if (g_agi->getVersion() >= 0x3000) { - g_agi->setLoop(&vt, vt.currentLoop); - g_agi->setCel(&vt, vt.currentCel); + if (getVersion() >= 0x3000) { + setLoop(&vt, vt.currentLoop); + setCel(&vt, vt.currentCel); } - g_agi->fixPosition(p0); + fixPosition(p0); vt.xPos2 = vt.xPos; vt.yPos2 = vt.yPos; vt.celData2 = vt.celData; - g_sprites->eraseUpdSprites(); + _sprites->eraseUpdSprites(); vt.flags |= DRAWN; - // WORKAROUND: This fixes a bug with AGI Fanmade game Space Trek. + // WORKAROUND: This fixes a bug with AGI Fanmade _game Space Trek. // The original workaround checked if AGI version was <= 2.440, which could // cause regressions with some AGI games. The original workaround no longer // works for Space Trek in ScummVM, as all fanmade games are set to use @@ -875,36 +854,43 @@ cmd(draw) { // TODO: Investigate this further and check if any other fanmade AGI // games are affected. If yes, then it'd be best to set this for Space // Trek only - if (g_agi->getFeatures() & GF_FANMADE) // See Sarien bug #546562 + if (getFeatures() & GF_FANMADE) // See Sarien bug #546562 vt.flags |= ANIMATED; - g_sprites->blitUpdSprites(); + _sprites->blitUpdSprites(); vt.flags &= ~DONTUPDATE; - g_sprites->commitBlock(vt.xPos, vt.yPos - vt.ySize + 1, vt.xPos + vt.xSize - 1, vt.yPos); + _sprites->commitBlock(vt.xPos, vt.yPos - vt.ySize + 1, vt.xPos + vt.xSize - 1, vt.yPos, true); debugC(4, kDebugLevelScripts, "vt entry #%d flags = %02x", p0, vt.flags); } -cmd(erase) { +void AgiEngine::cmd_erase(uint8 *p) { if (~vt.flags & DRAWN) return; - g_sprites->eraseUpdSprites(); + _sprites->eraseUpdSprites(); if (vt.flags & UPDATE) { vt.flags &= ~DRAWN; } else { - g_sprites->eraseNonupdSprites(); + _sprites->eraseNonupdSprites(); vt.flags &= ~DRAWN; - g_sprites->blitNonupdSprites(); + _sprites->blitNonupdSprites(); } - g_sprites->blitUpdSprites(); + _sprites->blitUpdSprites(); + + int x1, y1, x2, y2; + + x1 = MIN((int)MIN(vt.xPos, vt.xPos2), MIN(vt.xPos + vt.celData->width, vt.xPos2 + vt.celData2->width)); + x2 = MAX((int)MAX(vt.xPos, vt.xPos2), MAX(vt.xPos + vt.celData->width, vt.xPos2 + vt.celData2->width)); + y1 = MIN((int)MIN(vt.yPos, vt.yPos2), MIN(vt.yPos - vt.celData->height, vt.yPos2 - vt.celData2->height)); + y2 = MAX((int)MAX(vt.yPos, vt.yPos2), MAX(vt.yPos - vt.celData->height, vt.yPos2 - vt.celData2->height)); - g_sprites->commitBlock(vt.xPos, vt.yPos - vt.ySize + 1, vt.xPos + vt.xSize - 1, vt.yPos); + _sprites->commitBlock(x1, y1, x2, y2, true); } -cmd(position) { +void AgiEngine::cmd_position(uint8 *p) { vt.xPos = vt.xPos2 = p1; vt.yPos = vt.yPos2 = p2; @@ -921,27 +907,27 @@ cmd(position) { // I haven't checked but if Space Trek solely abuses the position-command we wouldn't // strictly need the identical workaround in the position.v-command but it does make // for a nice symmetry. - if (g_agi->getFeatures() & GF_CLIPCOORDS) - g_agi->clipViewCoordinates(&vt); + if (getFeatures() & GF_CLIPCOORDS) + clipViewCoordinates(&vt); } -cmd(position_f) { +void AgiEngine::cmd_position_f(uint8 *p) { vt.xPos = vt.xPos2 = _v[p1]; vt.yPos = vt.yPos2 = _v[p2]; // WORKAROUND: Part of the fix for bug #1659209 "AGI: Space Trek sprite duplication" // with an accompanying identical workaround in position-command (i.e. command 0x25). // See that workaround's comment for more in-depth information. - if (g_agi->getFeatures() & GF_CLIPCOORDS) - g_agi->clipViewCoordinates(&vt); + if (getFeatures() & GF_CLIPCOORDS) + clipViewCoordinates(&vt); } -cmd(get_posn) { - game.vars[p1] = (unsigned char)vt.xPos; - game.vars[p2] = (unsigned char)vt.yPos; +void AgiEngine::cmd_get_posn(uint8 *p) { + _game.vars[p1] = (unsigned char)vt.xPos; + _game.vars[p2] = (unsigned char)vt.yPos; } -cmd(reposition) { +void AgiEngine::cmd_reposition(uint8 *p) { int dx = (int8) _v[p1], dy = (int8) _v[p2]; debugC(4, kDebugLevelScripts, "dx=%d, dy=%d", dx, dy); @@ -957,106 +943,106 @@ cmd(reposition) { else vt.yPos += dy; - g_agi->fixPosition(p0); + fixPosition(p0); } -cmd(reposition_to) { +void AgiEngine::cmd_reposition_to(uint8 *p) { vt.xPos = p1; vt.yPos = p2; vt.flags |= UPDATE_POS; - g_agi->fixPosition(p0); + fixPosition(p0); } -cmd(reposition_to_f) { +void AgiEngine::cmd_reposition_to_f(uint8 *p) { vt.xPos = _v[p1]; vt.yPos = _v[p2]; vt.flags |= UPDATE_POS; - g_agi->fixPosition(p0); + fixPosition(p0); } -cmd(add_to_pic) { - g_sprites->addToPic(p0, p1, p2, p3, p4, p5, p6); +void AgiEngine::cmd_add_to_pic(uint8 *p) { + _sprites->addToPic(p0, p1, p2, p3, p4, p5, p6); } -cmd(add_to_pic_f) { - g_sprites->addToPic(_v[p0], _v[p1], _v[p2], _v[p3], _v[p4], _v[p5], _v[p6]); +void AgiEngine::cmd_add_to_pic_f(uint8 *p) { + _sprites->addToPic(_v[p0], _v[p1], _v[p2], _v[p3], _v[p4], _v[p5], _v[p6]); } -cmd(force_update) { - g_sprites->eraseBoth(); - g_sprites->blitBoth(); - g_sprites->commitBoth(); +void AgiEngine::cmd_force_update(uint8 *p) { + _sprites->eraseBoth(); + _sprites->blitBoth(); + _sprites->commitBoth(); } -cmd(reverse_loop) { +void AgiEngine::cmd_reverse_loop(uint8 *p) { debugC(4, kDebugLevelScripts, "o%d, f%d", p0, p1); vt.cycle = CYCLE_REV_LOOP; vt.flags |= (DONTUPDATE | UPDATE | CYCLING); vt.parm1 = p1; - g_agi->setflag(p1, false); + setflag(p1, false); } -cmd(end_of_loop) { +void AgiEngine::cmd_end_of_loop(uint8 *p) { debugC(4, kDebugLevelScripts, "o%d, f%d", p0, p1); vt.cycle = CYCLE_END_OF_LOOP; vt.flags |= (DONTUPDATE | UPDATE | CYCLING); vt.parm1 = p1; - g_agi->setflag(p1, false); + setflag(p1, false); } -cmd(block) { +void AgiEngine::cmd_block(uint8 *p) { debugC(4, kDebugLevelScripts, "x1=%d, y1=%d, x2=%d, y2=%d", p0, p1, p2, p3); - game.block.active = true; - game.block.x1 = p0; - game.block.y1 = p1; - game.block.x2 = p2; - game.block.y2 = p3; + _game.block.active = true; + _game.block.x1 = p0; + _game.block.y1 = p1; + _game.block.x2 = p2; + _game.block.y2 = p3; } -cmd(unblock) { - game.block.active = false; +void AgiEngine::cmd_unblock(uint8 *p) { + _game.block.active = false; } -cmd(normal_motion) { +void AgiEngine::cmd_normal_motion(uint8 *p) { vt.motion = MOTION_NORMAL; } -cmd(stop_motion) { +void AgiEngine::cmd_stop_motion(uint8 *p) { vt.direction = 0; vt.motion = MOTION_NORMAL; if (p0 == 0) { // ego only _v[vEgoDir] = 0; - game.playerControl = false; + _game.playerControl = false; } } -cmd(start_motion) { +void AgiEngine::cmd_start_motion(uint8 *p) { vt.motion = MOTION_NORMAL; if (p0 == 0) { // ego only _v[vEgoDir] = 0; - game.playerControl = true; + _game.playerControl = true; } } -cmd(player_control) { - game.playerControl = true; - game.viewTable[0].motion = MOTION_NORMAL; +void AgiEngine::cmd_player_control(uint8 *p) { + _game.playerControl = true; + _game.viewTable[0].motion = MOTION_NORMAL; } -cmd(program_control) { - game.playerControl = false; +void AgiEngine::cmd_program_control(uint8 *p) { + _game.playerControl = false; } -cmd(follow_ego) { +void AgiEngine::cmd_follow_ego(uint8 *p) { vt.motion = MOTION_FOLLOW_EGO; vt.parm1 = p1 > vt.stepSize ? p1 : vt.stepSize; vt.parm2 = p2; vt.parm3 = 0xff; - g_agi->setflag(p2, false); + setflag(p2, false); vt.flags |= UPDATE; } -cmd(move_obj) { +void AgiEngine::cmd_move_obj(uint8 *p) { // _D (_D_WARN "o=%d, x=%d, y=%d, s=%d, f=%d", p0, p1, p2, p3, p4); vt.motion = MOTION_MOVE_OBJ; @@ -1068,18 +1054,18 @@ cmd(move_obj) { if (p3 != 0) vt.stepSize = p3; - g_agi->setflag(p4, false); + setflag(p4, false); vt.flags |= UPDATE; if (p0 == 0) - game.playerControl = false; + _game.playerControl = false; // AGI 2.272 (ddp, xmas) doesn't call move_obj! - if (g_agi->getVersion() > 0x2272) - g_agi->moveObj(&vt); + if (getVersion() > 0x2272) + moveObj(&vt); } -cmd(move_obj_f) { +void AgiEngine::cmd_move_obj_f(uint8 *p) { vt.motion = MOTION_MOVE_OBJ; vt.parm1 = _v[p1]; vt.parm2 = _v[p2]; @@ -1089,67 +1075,67 @@ cmd(move_obj_f) { if (_v[p3] != 0) vt.stepSize = _v[p3]; - g_agi->setflag(p4, false); + setflag(p4, false); vt.flags |= UPDATE; if (p0 == 0) - game.playerControl = false; + _game.playerControl = false; // AGI 2.272 (ddp, xmas) doesn't call move_obj! - if (g_agi->getVersion() > 0x2272) - g_agi->moveObj(&vt); + if (getVersion() > 0x2272) + moveObj(&vt); } -cmd(wander) { +void AgiEngine::cmd_wander(uint8 *p) { if (p0 == 0) - game.playerControl = false; + _game.playerControl = false; vt.motion = MOTION_WANDER; vt.flags |= UPDATE; } -cmd(set_game_id) { - if (curLogic->texts && (p0 - 1) <= curLogic->numTexts) - strncpy(game.id, curLogic->texts[p0 - 1], 8); +void AgiEngine::cmd_set_game_id(uint8 *p) { + if (_curLogic->texts && (p0 - 1) <= _curLogic->numTexts) + strncpy(_game.id, _curLogic->texts[p0 - 1], 8); else - game.id[0] = 0; + _game.id[0] = 0; - report("Game ID: \"%s\"\n", game.id); + report("Game ID: \"%s\"\n", _game.id); } -cmd(pause) { - int tmp = game.clockEnabled; +void AgiEngine::cmd_pause(uint8 *p) { + int tmp = _game.clockEnabled; const char *b[] = { "Continue", NULL }; const char *b_ru[] = { "\x8f\xe0\xae\xa4\xae\xab\xa6\xa8\xe2\xec", NULL }; - game.clockEnabled = false; + _game.clockEnabled = false; - switch (g_agi->getLanguage()) { + switch (getLanguage()) { case Common::RU_RUS: - g_agi->selectionBox(" \x88\xa3\xe0\xa0 \xae\xe1\xe2\xa0\xad\xae\xa2\xab\xa5\xad\xa0. \n\n\n", b_ru); + selectionBox(" \x88\xa3\xe0\xa0 \xae\xe1\xe2\xa0\xad\xae\xa2\xab\xa5\xad\xa0. \n\n\n", b_ru); break; default: - g_agi->selectionBox(" Game is paused. \n\n\n", b); + selectionBox(" Game is paused. \n\n\n", b); break; } - game.clockEnabled = tmp; + _game.clockEnabled = tmp; } -cmd(set_menu) { - debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, curLogic->numTexts); +void AgiEngine::cmd_set_menu(uint8 *p) { + debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, _curLogic->numTexts); - if (curLogic->texts != NULL && p0 <= curLogic->numTexts) - g_agi->_menu->add(curLogic->texts[p0 - 1]); + if (_curLogic->texts != NULL && p0 <= _curLogic->numTexts) + _menu->add(_curLogic->texts[p0 - 1]); } -cmd(set_menu_item) { - debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, curLogic->numTexts); +void AgiEngine::cmd_set_menu_item(uint8 *p) { + debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, _curLogic->numTexts); - if (curLogic->texts != NULL && p0 <= curLogic->numTexts) - g_agi->_menu->addItem(curLogic->texts[p0 - 1], p1); + if (_curLogic->texts != NULL && p0 <= _curLogic->numTexts) + _menu->addItem(_curLogic->texts[p0 - 1], p1); } -cmd(version) { +void AgiEngine::cmd_version(uint8 *p) { char verMsg[64]; char ver2Msg[] = "\n" @@ -1168,7 +1154,7 @@ cmd(version) { sprintf(verMsg, TITLE " v%s", gScummVMVersion); - ver = g_agi->getVersion(); + ver = getVersion(); maj = (ver >> 12) & 0xf; min = ver & 0xfff; @@ -1186,88 +1172,88 @@ cmd(version) { strncpy(q + 1 + gap, verMsg, strlen(verMsg)); sprintf(msg, q, maj, min); - g_agi->messageBox(msg); + messageBox(msg); } -cmd(configure_screen) { - game.lineMinPrint = p0; - game.lineUserInput = p1; - game.lineStatus = p2; +void AgiEngine::cmd_configure_screen(uint8 *p) { + _game.lineMinPrint = p0; + _game.lineUserInput = p1; + _game.lineStatus = p2; } -cmd(text_screen) { +void AgiEngine::cmd_text_screen(uint8 *p) { debugC(4, kDebugLevelScripts, "switching to text mode"); - game.gfxMode = false; + _game.gfxMode = false; // Simulates the "bright background bit" of the PC video // controller. - if (game.colorBg) - game.colorBg |= 0x08; + if (_game.colorBg) + _game.colorBg |= 0x08; - g_gfx->clearScreen(game.colorBg); + _gfx->clearScreen(_game.colorBg); } -cmd(graphics) { +void AgiEngine::cmd_graphics(uint8 *p) { debugC(4, kDebugLevelScripts, "switching to graphics mode"); - if (!game.gfxMode) { - game.gfxMode = true; - g_gfx->clearScreen(0); - g_picture->showPic(); - g_agi->writeStatus(); - g_agi->writePrompt(); + if (!_game.gfxMode) { + _game.gfxMode = true; + _gfx->clearScreen(0); + _picture->showPic(); + writeStatus(); + writePrompt(); } } -cmd(set_text_attribute) { - game.colorFg = p0; - game.colorBg = p1; +void AgiEngine::cmd_set_text_attribute(uint8 *p) { + _game.colorFg = p0; + _game.colorBg = p1; - if (game.gfxMode) { - if (game.colorBg != 0) { - game.colorFg = 0; - game.colorBg = 15; + if (_game.gfxMode) { + if (_game.colorBg != 0) { + _game.colorFg = 0; + _game.colorBg = 15; } } } -cmd(status) { - g_agi->inventory(); +void AgiEngine::cmd_status(uint8 *p) { + inventory(); } -cmd(quit) { +void AgiEngine::cmd_quit(uint8 *p) { const char *buttons[] = { "Quit", "Continue", NULL }; - g_sound->stopSound(); + _sound->stopSound(); if (p0) { - g_agi->quitGame(); + quitGame(); } else { - if (g_agi->selectionBox - (" Quit the game, or continue? \n\n\n", buttons) == 0) { - g_agi->quitGame(); + if (selectionBox + (" Quit the _game, or continue? \n\n\n", buttons) == 0) { + quitGame(); } } } -cmd(restart_game) { +void AgiEngine::cmd_restart_game(uint8 *p) { const char *buttons[] = { "Restart", "Continue", NULL }; int sel; - g_sound->stopSound(); - sel = g_agi->getflag(fAutoRestart) ? 0 : - g_agi->selectionBox(" Restart game, or continue? \n\n\n", buttons); + _sound->stopSound(); + sel = getflag(fAutoRestart) ? 0 : + selectionBox(" Restart _game, or continue? \n\n\n", buttons); if (sel == 0) { - g_agi->_restartGame = true; - g_agi->setflag(fRestartGame, true); - g_agi->_menu->enableAll(); + _restartGame = true; + setflag(fRestartGame, true); + _menu->enableAll(); } } -cmd(distance) { +void AgiEngine::cmd_distance(uint8 *p) { int16 x1, y1, x2, y2, d; - VtEntry *v0 = &game.viewTable[p0]; - VtEntry *v1 = &game.viewTable[p1]; + VtEntry *v0 = &_game.viewTable[p0]; + VtEntry *v1 = &_game.viewTable[p1]; if (v0->flags & DRAWN && v1->flags & DRAWN) { x1 = v0->xPos + v0->xSize / 2; @@ -1290,7 +1276,7 @@ cmd(distance) { // wouldn't chase Rosella around anymore. If it had worked correctly the zombie // wouldn't have come up at all or it would have come up and gone back down // immediately. The latter approach is the one implemented here. - if (g_agi->getGameID() == GID_KQ4 && (_v[vCurRoom] == 16 || _v[vCurRoom] == 18) && p2 >= 221 && p2 <= 223) { + if (getGameID() == GID_KQ4 && (_v[vCurRoom] == 16 || _v[vCurRoom] == 18) && p2 >= 221 && p2 <= 223) { // Rooms 16 and 18 are graveyards where three zombies come up at night. They use logics 16 and 18. // Variables 221-223 are used to save the distance between each zombie and Rosella. // Variables 155, 156 and 162 are used to save the state of each zombie in room 16. @@ -1315,24 +1301,24 @@ cmd(distance) { _v[p2] = (unsigned char)d; } -cmd(accept_input) { +void AgiEngine::cmd_accept_input(uint8 *p) { debugC(4, kDebugLevelScripts | kDebugLevelInput, "input normal"); - g_agi->newInputMode(INPUT_NORMAL); - game.inputEnabled = true; - g_agi->writePrompt(); + newInputMode(INPUT_NORMAL); + _game.inputEnabled = true; + writePrompt(); } -cmd(prevent_input) { +void AgiEngine::cmd_prevent_input(uint8 *p) { debugC(4, kDebugLevelScripts | kDebugLevelInput, "no input"); - g_agi->newInputMode(INPUT_NONE); - game.inputEnabled = false; + newInputMode(INPUT_NONE); + _game.inputEnabled = false; - g_agi->clearPrompt(); + clearPrompt(); } -cmd(get_string) { +void AgiEngine::cmd_get_string(uint8 *p) { int tex, row, col; debugC(4, kDebugLevelScripts, "%d %d %d %d %d", p0, p1, p2, p3, p4); @@ -1348,63 +1334,63 @@ cmd(get_string) { if (col > 39) col = 39; - g_agi->newInputMode(INPUT_GETSTRING); + newInputMode(INPUT_GETSTRING); - if (curLogic->texts != NULL && curLogic->numTexts >= tex) { - int len = strlen(curLogic->texts[tex]); + if (_curLogic->texts != NULL && _curLogic->numTexts >= tex) { + int len = strlen(_curLogic->texts[tex]); - g_agi->printText(curLogic->texts[tex], 0, col, row, len, game.colorFg, game.colorBg); - g_agi->getString(col + len - 1, row, p4, p0); + printText(_curLogic->texts[tex], 0, col, row, len, _game.colorFg, _game.colorBg); + getString(col + len - 1, row, p4, p0); // SGEO: display input char - g_gfx->printCharacter((col + len), row, game.cursorChar, game.colorFg, game.colorBg); + _gfx->printCharacter((col + len), row, _game.cursorChar, _game.colorFg, _game.colorBg); } do { - g_agi->mainCycle(); - } while (game.inputMode == INPUT_GETSTRING && !(g_agi->shouldQuit() || g_agi->_restartGame)); + mainCycle(); + } while (_game.inputMode == INPUT_GETSTRING && !(shouldQuit() || _restartGame)); } -cmd(get_num) { +void AgiEngine::cmd_get_num(uint8 *p) { debugC(4, kDebugLevelScripts, "%d %d", p0, p1); - g_agi->newInputMode(INPUT_GETSTRING); + newInputMode(INPUT_GETSTRING); - if (curLogic->texts != NULL && curLogic->numTexts >= (p0 - 1)) { - int len = strlen(curLogic->texts[p0 - 1]); + if (_curLogic->texts != NULL && _curLogic->numTexts >= (p0 - 1)) { + int len = strlen(_curLogic->texts[p0 - 1]); - g_agi->printText(curLogic->texts[p0 - 1], 0, 0, 22, len, game.colorFg, game.colorBg); - g_agi->getString(len - 1, 22, 3, MAX_STRINGS); + printText(_curLogic->texts[p0 - 1], 0, 0, 22, len, _game.colorFg, _game.colorBg); + getString(len - 1, 22, 3, MAX_STRINGS); // CM: display input char - g_gfx->printCharacter((p3 + len), 22, game.cursorChar, game.colorFg, game.colorBg); + _gfx->printCharacter((p3 + len), 22, _game.cursorChar, _game.colorFg, _game.colorBg); } do { - g_agi->mainCycle(); - } while (game.inputMode == INPUT_GETSTRING && !(g_agi->shouldQuit() || g_agi->_restartGame)); + mainCycle(); + } while (_game.inputMode == INPUT_GETSTRING && !(shouldQuit() || _restartGame)); - _v[p1] = atoi(game.strings[MAX_STRINGS]); + _v[p1] = atoi(_game.strings[MAX_STRINGS]); - debugC(4, kDebugLevelScripts, "[%s] -> %d", game.strings[MAX_STRINGS], _v[p1]); + debugC(4, kDebugLevelScripts, "[%s] -> %d", _game.strings[MAX_STRINGS], _v[p1]); - g_agi->clearLines(22, 22, game.colorBg); - g_agi->flushLines(22, 22); + clearLines(22, 22, _game.colorBg); + flushLines(22, 22); } -cmd(set_cursor_char) { - if (curLogic->texts != NULL && (p0 - 1) <= curLogic->numTexts) { - game.cursorChar = *curLogic->texts[p0 - 1]; +void AgiEngine::cmd_set_cursor_char(uint8 *p) { + if (_curLogic->texts != NULL && (p0 - 1) <= _curLogic->numTexts) { + _game.cursorChar = *_curLogic->texts[p0 - 1]; } else { // default - game.cursorChar = '_'; + _game.cursorChar = '_'; } } -cmd(set_key) { +void AgiEngine::cmd_set_key(uint8 *p) { int key; - if (game.lastController >= MAX_CONTROLLERS) { + if (_game.lastController >= MAX_CONTROLLERS) { warning("Number of set.keys exceeded %d", MAX_CONTROLLERS); return; } @@ -1413,36 +1399,35 @@ cmd(set_key) { key = 256 * p1 + p0; - game.controllers[game.lastController].keycode = key; - game.controllers[game.lastController].controller = p2; - game.lastController++; + _game.controllers[_game.lastController].keycode = key; + _game.controllers[_game.lastController].controller = p2; + _game.lastController++; - game.controllerOccured[p2] = false; + _game.controllerOccured[p2] = false; } -cmd(set_string) { +void AgiEngine::cmd_set_string(uint8 *p) { // CM: to avoid crash in Groza (str = 150) if (p0 > MAX_STRINGS) return; - strcpy(game.strings[p0], curLogic->texts[p1 - 1]); + strcpy(_game.strings[p0], _curLogic->texts[p1 - 1]); } -cmd(display) { +void AgiEngine::cmd_display(uint8 *p) { int len = 40; - char *s = g_agi->wordWrapString(curLogic->texts[p2 - 1], &len); + char *s = wordWrapString(_curLogic->texts[p2 - 1], &len); - g_agi->printText(s, p1, 0, p0, 40, game.colorFg, game.colorBg); + printText(s, p1, 0, p0, 40, _game.colorFg, _game.colorBg); free(s); } -cmd(display_f) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); - g_agi->printText(curLogic->texts[_v[p2] - 1], _v[p1], 0, _v[p0], 40, game.colorFg, game.colorBg); +void AgiEngine::cmd_display_f(uint8 *p) { + printText(_curLogic->texts[_v[p2] - 1], _v[p1], 0, _v[p0], 40, _game.colorFg, _game.colorBg); } -cmd(clear_text_rect) { +void AgiEngine::cmd_clear_text_rect(uint8 *p) { int c, x1, y1, x2, y2; if ((c = p4) != 0) @@ -1463,21 +1448,21 @@ cmd(clear_text_rect) { if (y2 > GFX_HEIGHT) y2 = GFX_HEIGHT - 1; - g_gfx->drawRectangle(x1, y1, x2, y2, c); - g_gfx->flushBlock(x1, y1, x2, y2); + _gfx->drawRectangle(x1, y1, x2, y2, c); + _gfx->flushBlock(x1, y1, x2, y2); } -cmd(toggle_monitor) { +void AgiEngine::cmd_toggle_monitor(uint8 *p) { report("toggle.monitor\n"); } -cmd(echo_line) { - strcpy((char *)game.inputBuffer, (const char *)game.echoBuffer); - game.cursorPos = strlen((char *)game.inputBuffer); - game.hasPrompt = 0; +void AgiEngine::cmd_echo_line(uint8 *p) { + strcpy((char *)_game.inputBuffer, (const char *)_game.echoBuffer); + _game.cursorPos = strlen((char *)_game.inputBuffer); + _game.hasPrompt = 0; } -cmd(clear_lines) { +void AgiEngine::cmd_clear_lines(uint8 *p) { uint8 l; // Residence 44 calls clear.lines(24,0,0), see Sarien bug #558423 @@ -1487,78 +1472,78 @@ cmd(clear_lines) { // #1935838 and #1935842 l = (l <= 24) ? l : 24; - g_agi->clearLines(p0, l, p2); - g_agi->flushLines(p0, l); + clearLines(p0, l, p2); + flushLines(p0, l); } -cmd(print) { +void AgiEngine::cmd_print(uint8 *p) { int n = p0 < 1 ? 1 : p0; - g_agi->print(curLogic->texts[n - 1], 0, 0, 0); + print(_curLogic->texts[n - 1], 0, 0, 0); } -cmd(print_f) { +void AgiEngine::cmd_print_f(uint8 *p) { int n = _v[p0] < 1 ? 1 : _v[p0]; - g_agi->print(curLogic->texts[n - 1], 0, 0, 0); + print(_curLogic->texts[n - 1], 0, 0, 0); } -cmd(print_at) { +void AgiEngine::cmd_print_at(uint8 *p) { int n = p0 < 1 ? 1 : p0; debugC(4, kDebugLevelScripts, "%d %d %d %d", p0, p1, p2, p3); - g_agi->print(curLogic->texts[n - 1], p1, p2, p3); + print(_curLogic->texts[n - 1], p1, p2, p3); } -cmd(print_at_v) { +void AgiEngine::cmd_print_at_v(uint8 *p) { int n = _v[p0] < 1 ? 1 : _v[p0]; - g_agi->print(curLogic->texts[n - 1], p1, p2, p3); + print(_curLogic->texts[n - 1], p1, p2, p3); } -cmd(push_script) { +void AgiEngine::cmd_push_script(uint8 *p) { // We run AGIMOUSE always as a side effect - if (g_agi->getFeatures() & GF_AGIMOUSE || 1) { - game.vars[27] = g_agi->_mouse.button; - game.vars[28] = g_agi->_mouse.x / 2; - game.vars[29] = g_agi->_mouse.y; + if (getFeatures() & GF_AGIMOUSE || 1) { + _game.vars[27] = _mouse.button; + _game.vars[28] = _mouse.x / 2; + _game.vars[29] = _mouse.y; } else { - if (g_agi->getVersion() >= 0x2915) { + if (getVersion() >= 0x2915) { report("push.script\n"); } } } -cmd(set_pri_base) { +void AgiEngine::cmd_set_pri_base(uint8 *p) { int i, x, pri; report("Priority base set to %d\n", p0); - // game.alt_pri = true; + // _game.alt_pri = true; x = (_HEIGHT - p0) * _HEIGHT / 10; for (i = 0; i < _HEIGHT; i++) { pri = (i - p0) < 0 ? 4 : (i - p0) * _HEIGHT / x + 5; if (pri > 15) pri = 15; - game.priTable[i] = pri; + _game.priTable[i] = pri; } } -cmd(mouse_posn) { - _v[p0] = WIN_TO_PIC_X(g_agi->_mouse.x); - _v[p1] = WIN_TO_PIC_Y(g_agi->_mouse.y); +void AgiEngine::cmd_mouse_posn(uint8 *p) { + _v[p0] = WIN_TO_PIC_X(_mouse.x); + _v[p1] = WIN_TO_PIC_Y(_mouse.y); } -cmd(shake_screen) { +void AgiEngine::cmd_shake_screen(uint8 *p) { int i; // AGIPAL uses shake.screen values between 100 and 109 to set the palette // (Checked the original AGIPAL-hack's shake.screen-routine's disassembly). if (p0 >= 100 && p0 < 110) { - if (g_agi->getFeatures() & GF_AGIPAL) { - g_gfx->setAGIPal(p0); + if (getFeatures() & GF_AGIPAL) { + _gfx->setAGIPal(p0); return; } else { warning("It looks like GF_AGIPAL flag is missing"); @@ -1567,208 +1552,213 @@ cmd(shake_screen) { // Disables input while shaking to prevent bug // #1678230: AGI: Entering text while screen is shaking - int originalValue = game.inputEnabled; - game.inputEnabled = 0; + bool originalValue = _game.inputEnabled; + _game.inputEnabled = false; - g_gfx->shakeStart(); + _gfx->shakeStart(); - g_sprites->commitBoth(); // Fixes SQ1 demo + _sprites->commitBoth(); // Fixes SQ1 demo for (i = 4 * p0; i; i--) { - g_gfx->shakeScreen(i & 1); - g_gfx->flushBlock(0, 0, GFX_WIDTH - 1, GFX_HEIGHT - 1); - g_agi->mainCycle(); + _gfx->shakeScreen(i & 1); + _gfx->flushBlock(0, 0, GFX_WIDTH - 1, GFX_HEIGHT - 1); + mainCycle(); } - g_gfx->shakeEnd(); + _gfx->shakeEnd(); // Sets input back to what it was - game.inputEnabled = originalValue; -} - -static void (*agiCommand[183])(AgiEngine *, uint8 *) = { - NULL, // 0x00 - cmd_increment, - cmd_decrement, - cmd_assignn, - cmd_assignv, - cmd_addn, - cmd_addv, - cmd_subn, - cmd_subv, // 0x08 - cmd_lindirectv, - cmd_rindirect, - cmd_lindirectn, - cmd_set, - cmd_reset, - cmd_toggle, - cmd_set_v, - cmd_reset_v, // 0x10 - cmd_toggle_v, - cmd_new_room, - cmd_new_room_f, - cmd_load_logic, - cmd_load_logic_f, - cmd_call, - cmd_call_f, - cmd_load_pic, // 0x18 - cmd_draw_pic, - cmd_show_pic, - cmd_discard_pic, - cmd_overlay_pic, - cmd_show_pri_screen, - cmd_load_view, - cmd_load_view_f, - cmd_discard_view, // 0x20 - cmd_animate_obj, - cmd_unanimate_all, - cmd_draw, - cmd_erase, - cmd_position, - cmd_position_f, - cmd_get_posn, - cmd_reposition, // 0x28 - cmd_set_view, - cmd_set_view_f, - cmd_set_loop, - cmd_set_loop_f, - cmd_fix_loop, - cmd_release_loop, - cmd_set_cel, - cmd_set_cel_f, // 0x30 - cmd_last_cel, - cmd_current_cel, - cmd_current_loop, - cmd_current_view, - cmd_number_of_loops, - cmd_set_priority, - cmd_set_priority_f, - cmd_release_priority, // 0x38 - cmd_get_priority, - cmd_stop_update, - cmd_start_update, - cmd_force_update, - cmd_ignore_horizon, - cmd_observe_horizon, - cmd_set_horizon, - cmd_object_on_water, // 0x40 - cmd_object_on_land, - cmd_object_on_anything, - cmd_ignore_objs, - cmd_observe_objs, - cmd_distance, - cmd_stop_cycling, - cmd_start_cycling, - cmd_normal_cycle, // 0x48 - cmd_end_of_loop, - cmd_reverse_cycle, - cmd_reverse_loop, - cmd_cycle_time, - cmd_stop_motion, - cmd_start_motion, - cmd_step_size, - cmd_step_time, // 0x50 - cmd_move_obj, - cmd_move_obj_f, - cmd_follow_ego, - cmd_wander, - cmd_normal_motion, - cmd_set_dir, - cmd_get_dir, - cmd_ignore_blocks, // 0x58 - cmd_observe_blocks, - cmd_block, - cmd_unblock, - cmd_get, - cmd_get_f, - cmd_drop, - cmd_put, - cmd_put_f, // 0x60 - cmd_get_room_f, - cmd_load_sound, - cmd_sound, - cmd_stop_sound, - cmd_print, - cmd_print_f, - cmd_display, - cmd_display_f, // 0x68 - cmd_clear_lines, - cmd_text_screen, - cmd_graphics, - cmd_set_cursor_char, - cmd_set_text_attribute, - cmd_shake_screen, - cmd_configure_screen, - cmd_status_line_on, // 0x70 - cmd_status_line_off, - cmd_set_string, - cmd_get_string, - cmd_word_to_string, - cmd_parse, - cmd_get_num, - cmd_prevent_input, - cmd_accept_input, // 0x78 - cmd_set_key, - cmd_add_to_pic, - cmd_add_to_pic_f, - cmd_status, - cmd_save_game, - cmd_load_game, - cmd_init_disk, - cmd_restart_game, // 0x80 - cmd_show_obj, - cmd_random, - cmd_program_control, - cmd_player_control, - cmd_obj_status_f, - cmd_quit, - cmd_show_mem, - cmd_pause, // 0x88 - cmd_echo_line, - cmd_cancel_line, - cmd_init_joy, - cmd_toggle_monitor, - cmd_version, - cmd_script_size, - cmd_set_game_id, - cmd_log, // 0x90 - cmd_set_scan_start, - cmd_reset_scan_start, - cmd_reposition_to, - cmd_reposition_to_f, - cmd_trace_on, - cmd_trace_info, - cmd_print_at, - cmd_print_at_v, // 0x98 - cmd_discard_view, - cmd_clear_text_rect, - cmd_set_upper_left, - cmd_set_menu, - cmd_set_menu_item, - cmd_submit_menu, - cmd_enable_item, - cmd_disable_item, // 0xa0 - cmd_menu_input, - cmd_show_obj_v, - cmd_open_dialogue, - cmd_close_dialogue, - cmd_mul_n, - cmd_mul_v, - cmd_div_n, - cmd_div_v, // 0xa8 - cmd_close_window, - cmd_set_simple, - cmd_push_script, - cmd_pop_script, - cmd_hold_key, - cmd_set_pri_base, - cmd_discard_sound, - cmd_hide_mouse, // 0xb0 - cmd_allow_menu, - cmd_show_mouse, - cmd_fence_mouse, - cmd_mouse_posn, - cmd_release_key, - cmd_adj_ego_move_to_x_y -}; + _game.inputEnabled = originalValue; +} + +void AgiEngine::setupOpcodes() { + AgiCommand tmp[] = { + NULL, // 0x00 + &AgiEngine::cmd_increment, + &AgiEngine::cmd_decrement, + &AgiEngine::cmd_assignn, + &AgiEngine::cmd_assignv, + &AgiEngine::cmd_addn, + &AgiEngine::cmd_addv, + &AgiEngine::cmd_subn, + &AgiEngine::cmd_subv, // 0x08 + &AgiEngine::cmd_lindirectv, + &AgiEngine::cmd_rindirect, + &AgiEngine::cmd_lindirectn, + &AgiEngine::cmd_set, + &AgiEngine::cmd_reset, + &AgiEngine::cmd_toggle, + &AgiEngine::cmd_set_v, + &AgiEngine::cmd_reset_v, // 0x10 + &AgiEngine::cmd_toggle_v, + &AgiEngine::cmd_new_room, + &AgiEngine::cmd_new_room_f, + &AgiEngine::cmd_load_logic, + &AgiEngine::cmd_load_logic_f, + &AgiEngine::cmd_call, + &AgiEngine::cmd_call_f, + &AgiEngine::cmd_load_pic, // 0x18 + &AgiEngine::cmd_draw_pic, + &AgiEngine::cmd_show_pic, + &AgiEngine::cmd_discard_pic, + &AgiEngine::cmd_overlay_pic, + &AgiEngine::cmd_show_pri_screen, + &AgiEngine::cmd_load_view, + &AgiEngine::cmd_load_view_f, + &AgiEngine::cmd_discard_view, // 0x20 + &AgiEngine::cmd_animate_obj, + &AgiEngine::cmd_unanimate_all, + &AgiEngine::cmd_draw, + &AgiEngine::cmd_erase, + &AgiEngine::cmd_position, + &AgiEngine::cmd_position_f, + &AgiEngine::cmd_get_posn, + &AgiEngine::cmd_reposition, // 0x28 + &AgiEngine::cmd_set_view, + &AgiEngine::cmd_set_view_f, + &AgiEngine::cmd_set_loop, + &AgiEngine::cmd_set_loop_f, + &AgiEngine::cmd_fix_loop, + &AgiEngine::cmd_release_loop, + &AgiEngine::cmd_set_cel, + &AgiEngine::cmd_set_cel_f, // 0x30 + &AgiEngine::cmd_last_cel, + &AgiEngine::cmd_current_cel, + &AgiEngine::cmd_current_loop, + &AgiEngine::cmd_current_view, + &AgiEngine::cmd_number_of_loops, + &AgiEngine::cmd_set_priority, + &AgiEngine::cmd_set_priority_f, + &AgiEngine::cmd_release_priority, // 0x38 + &AgiEngine::cmd_get_priority, + &AgiEngine::cmd_stop_update, + &AgiEngine::cmd_start_update, + &AgiEngine::cmd_force_update, + &AgiEngine::cmd_ignore_horizon, + &AgiEngine::cmd_observe_horizon, + &AgiEngine::cmd_set_horizon, + &AgiEngine::cmd_object_on_water, // 0x40 + &AgiEngine::cmd_object_on_land, + &AgiEngine::cmd_object_on_anything, + &AgiEngine::cmd_ignore_objs, + &AgiEngine::cmd_observe_objs, + &AgiEngine::cmd_distance, + &AgiEngine::cmd_stop_cycling, + &AgiEngine::cmd_start_cycling, + &AgiEngine::cmd_normal_cycle, // 0x48 + &AgiEngine::cmd_end_of_loop, + &AgiEngine::cmd_reverse_cycle, + &AgiEngine::cmd_reverse_loop, + &AgiEngine::cmd_cycle_time, + &AgiEngine::cmd_stop_motion, + &AgiEngine::cmd_start_motion, + &AgiEngine::cmd_step_size, + &AgiEngine::cmd_step_time, // 0x50 + &AgiEngine::cmd_move_obj, + &AgiEngine::cmd_move_obj_f, + &AgiEngine::cmd_follow_ego, + &AgiEngine::cmd_wander, + &AgiEngine::cmd_normal_motion, + &AgiEngine::cmd_set_dir, + &AgiEngine::cmd_get_dir, + &AgiEngine::cmd_ignore_blocks, // 0x58 + &AgiEngine::cmd_observe_blocks, + &AgiEngine::cmd_block, + &AgiEngine::cmd_unblock, + &AgiEngine::cmd_get, + &AgiEngine::cmd_get_f, + &AgiEngine::cmd_drop, + &AgiEngine::cmd_put, + &AgiEngine::cmd_put_f, // 0x60 + &AgiEngine::cmd_get_room_f, + &AgiEngine::cmd_load_sound, + &AgiEngine::cmd_sound, + &AgiEngine::cmd_stop_sound, + &AgiEngine::cmd_print, + &AgiEngine::cmd_print_f, + &AgiEngine::cmd_display, + &AgiEngine::cmd_display_f, // 0x68 + &AgiEngine::cmd_clear_lines, + &AgiEngine::cmd_text_screen, + &AgiEngine::cmd_graphics, + &AgiEngine::cmd_set_cursor_char, + &AgiEngine::cmd_set_text_attribute, + &AgiEngine::cmd_shake_screen, + &AgiEngine::cmd_configure_screen, + &AgiEngine::cmd_status_line_on, // 0x70 + &AgiEngine::cmd_status_line_off, + &AgiEngine::cmd_set_string, + &AgiEngine::cmd_get_string, + &AgiEngine::cmd_word_to_string, + &AgiEngine::cmd_parse, + &AgiEngine::cmd_get_num, + &AgiEngine::cmd_prevent_input, + &AgiEngine::cmd_accept_input, // 0x78 + &AgiEngine::cmd_set_key, + &AgiEngine::cmd_add_to_pic, + &AgiEngine::cmd_add_to_pic_f, + &AgiEngine::cmd_status, + &AgiEngine::cmd_save_game, + &AgiEngine::cmd_load_game, + &AgiEngine::cmd_init_disk, + &AgiEngine::cmd_restart_game, // 0x80 + &AgiEngine::cmd_show_obj, + &AgiEngine::cmd_random, + &AgiEngine::cmd_program_control, + &AgiEngine::cmd_player_control, + &AgiEngine::cmd_obj_status_f, + &AgiEngine::cmd_quit, + &AgiEngine::cmd_show_mem, + &AgiEngine::cmd_pause, // 0x88 + &AgiEngine::cmd_echo_line, + &AgiEngine::cmd_cancel_line, + &AgiEngine::cmd_init_joy, + &AgiEngine::cmd_toggle_monitor, + &AgiEngine::cmd_version, + &AgiEngine::cmd_script_size, + &AgiEngine::cmd_set_game_id, + &AgiEngine::cmd_log, // 0x90 + &AgiEngine::cmd_set_scan_start, + &AgiEngine::cmd_reset_scan_start, + &AgiEngine::cmd_reposition_to, + &AgiEngine::cmd_reposition_to_f, + &AgiEngine::cmd_trace_on, + &AgiEngine::cmd_trace_info, + &AgiEngine::cmd_print_at, + &AgiEngine::cmd_print_at_v, // 0x98 + &AgiEngine::cmd_discard_view, // Opcode repeated from 0x20 ? + &AgiEngine::cmd_clear_text_rect, + &AgiEngine::cmd_set_upper_left, + &AgiEngine::cmd_set_menu, + &AgiEngine::cmd_set_menu_item, + &AgiEngine::cmd_submit_menu, + &AgiEngine::cmd_enable_item, + &AgiEngine::cmd_disable_item, // 0xa0 + &AgiEngine::cmd_menu_input, + &AgiEngine::cmd_show_obj_v, + &AgiEngine::cmd_open_dialogue, + &AgiEngine::cmd_close_dialogue, + &AgiEngine::cmd_mul_n, + &AgiEngine::cmd_mul_v, + &AgiEngine::cmd_div_n, + &AgiEngine::cmd_div_v, // 0xa8 + &AgiEngine::cmd_close_window, + &AgiEngine::cmd_set_simple, + &AgiEngine::cmd_push_script, + &AgiEngine::cmd_pop_script, + &AgiEngine::cmd_hold_key, + &AgiEngine::cmd_set_pri_base, + &AgiEngine::cmd_discard_sound, + &AgiEngine::cmd_hide_mouse, // 0xb0 + &AgiEngine::cmd_allow_menu, + &AgiEngine::cmd_show_mouse, + &AgiEngine::cmd_fence_mouse, + &AgiEngine::cmd_mouse_posn, + &AgiEngine::cmd_release_key, + &AgiEngine::cmd_adj_ego_move_to_x_y + }; + assert(ARRAYSIZE(_agiCommands) == ARRAYSIZE(tmp)); + for (int i = 0; i < ARRAYSIZE(tmp); ++i) + _agiCommands[i] = tmp[i]; +} /** * Execute a logic script @@ -1781,6 +1771,9 @@ int AgiEngine::runLogic(int n) { int num = 0; ScriptPos sp; + debugC(2, kDebugLevelScripts, "================="); + debugC(2, kDebugLevelScripts, "runLogic(%d)", n); + sp.script = n; sp.curIP = 0; _game.execStack.push_back(sp); @@ -1792,12 +1785,12 @@ int AgiEngine::runLogic(int n) { } _game.lognum = n; - curLogic = &_game.logics[_game.lognum]; + _curLogic = &_game.logics[_game.lognum]; - code = curLogic->data; - curLogic->cIP = curLogic->sIP; + code = _curLogic->data; + _curLogic->cIP = _curLogic->sIP; - timerHack = 0; + _timerHack = 0; while (ip < _game.logics[n].size && !(shouldQuit() || _restartGame)) { if (_debug.enabled) { if (_debug.steps > 0) { @@ -1807,6 +1800,7 @@ int AgiEngine::runLogic(int n) { } } else { _sprites->blitBoth(); + _sprites->commitBoth(); do { mainCycle(); } while (!_debug.steps && _debug.enabled); @@ -1816,6 +1810,11 @@ int AgiEngine::runLogic(int n) { _game.execStack.back().curIP = ip; + char st[101]; + int sz = MIN(_game.execStack.size(), 100u); + memset(st, '.', sz); + st[sz] = 0; + switch (op = *(code + ip++)) { case 0xff: // if (open/close) testIfCode(n); @@ -1826,13 +1825,16 @@ int AgiEngine::runLogic(int n) { // timer must keep running even in goto loops, // but AGI engine can't do that :( - if (timerHack > 20) { + if (_timerHack > 20) { pollTimer(); updateTimer(); - timerHack = 0; + _timerHack = 0; } break; case 0x00: // return + debugC(2, kDebugLevelScripts, "%sreturn() // Logic %d", st, n); + debugC(2, kDebugLevelScripts, "================="); + _game.execStack.pop_back(); return 1; default: @@ -1840,8 +1842,9 @@ int AgiEngine::runLogic(int n) { memmove(p, code + ip, num); memset(p + num, 0, CMD_BSIZE - num); - debugC(2, kDebugLevelScripts, "%s(%d %d %d)", logicNamesCmd[op].name, p[0], p[1], p[2]); - agiCommand[op](this, p); + debugC(2, kDebugLevelScripts, "%s%s(%d %d %d)", st, logicNamesCmd[op].name, p[0], p[1], p[2]); + + (this->*_agiCommands[op])(p); ip += num; } @@ -1857,7 +1860,7 @@ int AgiEngine::runLogic(int n) { void AgiEngine::executeAgiCommand(uint8 op, uint8 *p) { debugC(2, kDebugLevelScripts, "%s(%d %d %d)", logicNamesCmd[op].name, p[0], p[1], p[2]); - agiCommand[op] (this, p); + (this->*_agiCommands[op])(p); } } // End of namespace Agi diff --git a/engines/agi/op_test.cpp b/engines/agi/op_test.cpp index 71d307556b..ab4f6cadc5 100644 --- a/engines/agi/op_test.cpp +++ b/engines/agi/op_test.cpp @@ -29,37 +29,23 @@ namespace Agi { -static uint8 testObjRight(uint8, uint8, uint8, uint8, uint8); -static uint8 testObjCentre(uint8, uint8, uint8, uint8, uint8); -static uint8 testObjInBox(uint8, uint8, uint8, uint8, uint8); -static uint8 testPosn(uint8, uint8, uint8, uint8, uint8); -static uint8 testSaid(uint8, uint8 *); -static uint8 testController(uint8); -static uint8 testKeypressed(); -static uint8 testCompareStrings(uint8, uint8); - -static AgiEngine *g_agi; -#define game g_agi->_game - -#define ip (game.logics[lognum].cIP) -#define code (game.logics[lognum].data) - -#define testEqual(v1, v2) (g_agi->getvar(v1) == (v2)) -#define testLess(v1, v2) (g_agi->getvar(v1) < (v2)) -#define testGreater(v1, v2) (g_agi->getvar(v1) > (v2)) -#define testIsSet(flag) (g_agi->getflag(flag)) -#define testHas(obj) (g_agi->objectGetLocation(obj) == EGO_OWNED) -#define testObjInRoom(obj, v) (g_agi->objectGetLocation(obj) == g_agi->getvar(v)) - -extern int timerHack; // For the timer loop in MH1 logic 153 - -static uint8 testCompareStrings(uint8 s1, uint8 s2) { +#define ip (_game.logics[lognum].cIP) +#define code (_game.logics[lognum].data) + +#define testEqual(v1, v2) (getvar(v1) == (v2)) +#define testLess(v1, v2) (getvar(v1) < (v2)) +#define testGreater(v1, v2) (getvar(v1) > (v2)) +#define testIsSet(flag) (getflag(flag)) +#define testHas(obj) (objectGetLocation(obj) == EGO_OWNED) +#define testObjInRoom(obj, v) (objectGetLocation(obj) == getvar(v)) + +uint8 AgiEngine::testCompareStrings(uint8 s1, uint8 s2) { char ms1[MAX_STRINGLEN]; char ms2[MAX_STRINGLEN]; int j, k, l; - strcpy(ms1, game.strings[s1]); - strcpy(ms2, game.strings[s2]); + strcpy(ms1, _game.strings[s1]); + strcpy(ms2, _game.strings[s2]); l = strlen(ms1); for (k = 0, j = 0; k < l; k++) { @@ -106,16 +92,16 @@ static uint8 testCompareStrings(uint8 s1, uint8 s2) { return !strcmp(ms1, ms2); } -static uint8 testKeypressed() { - int x = game.keypress; +uint8 AgiEngine::testKeypressed() { + int x = _game.keypress; - game.keypress = 0; + _game.keypress = 0; if (!x) { - int mode = game.inputMode; + InputMode mode = _game.inputMode; - game.inputMode = INPUT_NONE; - g_agi->mainCycle(); - game.inputMode = mode; + _game.inputMode = INPUT_NONE; + mainCycle(); + _game.inputMode = mode; } if (x) @@ -124,12 +110,12 @@ static uint8 testKeypressed() { return x; } -static uint8 testController(uint8 cont) { - return (game.controllerOccured[cont] ? 1 : 0); +uint8 AgiEngine::testController(uint8 cont) { + return (_game.controllerOccured[cont] ? 1 : 0); } -static uint8 testPosn(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { - VtEntry *v = &game.viewTable[n]; +uint8 AgiEngine::testPosn(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { + VtEntry *v = &_game.viewTable[n]; uint8 r; r = v->xPos >= x1 && v->yPos >= y1 && v->xPos <= x2 && v->yPos <= y2; @@ -139,35 +125,35 @@ static uint8 testPosn(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { return r; } -static uint8 testObjInBox(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { - VtEntry *v = &game.viewTable[n]; +uint8 AgiEngine::testObjInBox(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { + VtEntry *v = &_game.viewTable[n]; return v->xPos >= x1 && v->yPos >= y1 && v->xPos + v->xSize - 1 <= x2 && v->yPos <= y2; } // if n is in centre of box -static uint8 testObjCentre(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { - VtEntry *v = &game.viewTable[n]; +uint8 AgiEngine::testObjCentre(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { + VtEntry *v = &_game.viewTable[n]; return v->xPos + v->xSize / 2 >= x1 && v->xPos + v->xSize / 2 <= x2 && v->yPos >= y1 && v->yPos <= y2; } // if nect N is in right corner -static uint8 testObjRight(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { - VtEntry *v = &game.viewTable[n]; +uint8 AgiEngine::testObjRight(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { + VtEntry *v = &_game.viewTable[n]; return v->xPos + v->xSize - 1 >= x1 && v->xPos + v->xSize - 1 <= x2 && v->yPos >= y1 && v->yPos <= y2; } // When player has entered something, it is parsed elsewhere -static uint8 testSaid(uint8 nwords, uint8 *cc) { - int c, n = game.numEgoWords; +uint8 AgiEngine::testSaid(uint8 nwords, uint8 *cc) { + int c, n = _game.numEgoWords; int z = 0; - if (g_agi->getflag(fSaidAcceptedInput) || !g_agi->getflag(fEnteredCli)) + if (getflag(fSaidAcceptedInput) || !getflag(fEnteredCli)) return false; // FR: @@ -198,7 +184,7 @@ static uint8 testSaid(uint8 nwords, uint8 *cc) { case 1: // any word break; default: - if (game.egoWords[c].id != z) + if (_game.egoWords[c].id != z) return false; break; } @@ -213,13 +199,12 @@ static uint8 testSaid(uint8 nwords, uint8 *cc) { if (nwords != 0 && READ_LE_UINT16(cc) != 9999) return false; - g_agi->setflag(fSaidAcceptedInput, true); + setflag(fSaidAcceptedInput, true); return true; } int AgiEngine::testIfCode(int lognum) { - g_agi = this; int ec = true; int retval = true; uint8 op = 0; @@ -263,32 +248,32 @@ int AgiEngine::testIfCode(int lognum) { case 0x01: ec = testEqual(p[0], p[1]); if (p[0] == 11) - timerHack++; + _timerHack++; break; case 0x02: ec = testEqual(p[0], getvar(p[1])); if (p[0] == 11 || p[1] == 11) - timerHack++; + _timerHack++; break; case 0x03: ec = testLess(p[0], p[1]); if (p[0] == 11) - timerHack++; + _timerHack++; break; case 0x04: ec = testLess(p[0], getvar(p[1])); if (p[0] == 11 || p[1] == 11) - timerHack++; + _timerHack++; break; case 0x05: ec = testGreater(p[0], p[1]); if (p[0] == 11) - timerHack++; + _timerHack++; break; case 0x06: ec = testGreater(p[0], getvar(p[1])); if (p[0] == 11 || p[1] == 11) - timerHack++; + _timerHack++; break; case 0x07: ec = testIsSet(p[0]); @@ -319,7 +304,7 @@ int AgiEngine::testIfCode(int lognum) { ip++; // skip num_words opcode break; case 0x0F: - debugC(7, kDebugLevelScripts, "comparing [%s], [%s]", game.strings[p[0]], game.strings[p[1]]); + debugC(7, kDebugLevelScripts, "comparing [%s], [%s]", _game.strings[p[0]], _game.strings[p[1]]); ec = testCompareStrings(p[0], p[1]); break; case 0x10: @@ -338,7 +323,7 @@ int AgiEngine::testIfCode(int lognum) { // This command is used at least in the Amiga version of Gold Rush! v2.05 1989-03-09 // (AGI 2.316) in logics 1, 3, 5, 6, 137 and 192 (Logic.192 revealed this command's nature). // TODO: Check this command's implementation using disassembly just to be sure. - ec = game.viewTable[0].flags & ADJ_EGO_XY; + ec = _game.viewTable[0].flags & ADJ_EGO_XY; debugC(7, kDebugLevelScripts, "op_test: in.motion.using.mouse = %s (Amiga-specific testcase 19)", ec ? "true" : "false"); break; default: diff --git a/engines/agi/picture.cpp b/engines/agi/picture.cpp index 60877de430..dc77433cb2 100644 --- a/engines/agi/picture.cpp +++ b/engines/agi/picture.cpp @@ -476,7 +476,7 @@ void PictureMgr::plotPattern(int x, int y) { // new purpose for temp16 - temp16 =( pen_size<<1) +1; // pen size + temp16 = (pen_size << 1) + 1; // pen size pen_final_y += temp16; // the last row of this shape temp16 = temp16 << 1; pen_width = temp16; // width of shape? @@ -495,7 +495,7 @@ void PictureMgr::plotPattern(int x, int y) { } else { circleCond = ((_patCode & 0x10) != 0); counterStep = 4; - ditherCond = 0x02; + ditherCond = 0x01; } for (; pen_y < pen_final_y; pen_y++) { @@ -503,10 +503,12 @@ void PictureMgr::plotPattern(int x, int y) { for (counter = 0; counter <= pen_width; counter += counterStep) { if (circleCond || ((binary_list[counter>>1] & circle_word) != 0)) { - temp8 = t % 2; - t = t >> 1; - if (temp8 != 0) - t = t ^ 0xB8; + if ((_patCode & 0x20) != 0) { + temp8 = t % 2; + t = t >> 1; + if (temp8 != 0) + t = t ^ 0xB8; + } // == box plot, != circle plot if ((_patCode & 0x20) == 0 || (t & 0x03) == ditherCond) diff --git a/engines/agi/preagi.cpp b/engines/agi/preagi.cpp index 35285798d4..1a5698dffc 100644 --- a/engines/agi/preagi.cpp +++ b/engines/agi/preagi.cpp @@ -68,8 +68,8 @@ void PreAgiEngine::initialize() { // drivers, and I'm not sure what they are. For now, they might // as well be called "PC Speaker" and "Not PC Speaker". - switch (MidiDriver::detectMusicDriver(MDT_PCSPK)) { - case MD_PCSPK: + switch (MidiDriver::getMusicType(MidiDriver::detectDevice(MDT_PCSPK))) { + case MT_PCSPK: _soundemu = SOUND_EMU_PC; break; default: diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp index b7e830dc53..88b14dcfe2 100644 --- a/engines/agi/saveload.cpp +++ b/engines/agi/saveload.cpp @@ -132,7 +132,7 @@ int AgiEngine::saveGame(const char *fileName, const char *description) { out->writeSint16BE((int16)_game.hasPrompt); out->writeSint16BE((int16)_game.gameFlags); - out->writeSint16BE((int16)_game.inputEnabled); + out->writeSint16BE(_game.inputEnabled); for (i = 0; i < _HEIGHT; i++) out->writeByte(_game.priTable[i]); @@ -302,7 +302,7 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) { // TODO: played time } - _game.state = in->readByte(); + _game.state = (State)in->readByte(); in->read(loadId, 8); if (strcmp(loadId, _game.id) && checkId) { @@ -361,7 +361,7 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) { _game.echoBuffer[0] = 0; _game.keypress = 0; - _game.inputMode = in->readSint16BE(); + _game.inputMode = (InputMode)in->readSint16BE(); _game.lognum = in->readSint16BE(); _game.playerControl = in->readSint16BE(); @@ -864,6 +864,10 @@ int AgiEngine::saveGameDialog() { sprintf(fileName, "%s", getSavegameFilename(_firstSlot + slot)); debugC(8, kDebugLevelMain | kDebugLevelResources, "file is [%s]", fileName); + // Make sure all graphics was blitted to screen. This fixes bug + // #2960567: "AGI: Ego partly erased in Load/Save thumbnails" + _gfx->doUpdate(); + int result = saveGame(fileName, desc); if (result == errOK) diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp index ca5d42d981..cb4e307ea6 100644 --- a/engines/agi/sound.cpp +++ b/engines/agi/sound.cpp @@ -23,23 +23,21 @@ * */ -#include "common/md5.h" -#include "common/config-manager.h" -#include "common/fs.h" -#include "common/random.h" -#include "common/str-array.h" - #include "agi/agi.h" -namespace Agi { +#include "agi/sound_2gs.h" +#include "agi/sound_coco3.h" +#include "agi/sound_midi.h" +#include "agi/sound_sarien.h" +#include "agi/sound_pcjr.h" -#define USE_INTERPOLATION +namespace Agi { // // TODO: add support for variable sampling rate in the output device // -AgiSound *AgiSound::createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager) { +AgiSound *AgiSound::createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager, int soundemu) { if (data == NULL || len < 2) // Check for too small resource or no resource at all return NULL; uint16 type = READ_LE_UINT16(data); @@ -48,27 +46,19 @@ AgiSound *AgiSound::createFromRawResource(uint8 *data, uint32 len, int resnum, S case AGI_SOUND_SAMPLE: return new IIgsSample(data, len, resnum, manager); case AGI_SOUND_MIDI: - return new IIgsMidi (data, len, resnum, manager); + return new IIgsMidi(data, len, resnum, manager); case AGI_SOUND_4CHN: - return new PCjrSound (data, len, resnum, manager); + if (soundemu == SOUND_EMU_MIDI) { + return new MIDISound(data, len, resnum, manager); + } else { + return new PCjrSound(data, len, resnum, manager); + } } warning("Sound resource (%d) has unknown type (0x%04x). Not using the sound", resnum, type); return NULL; } -IIgsMidi::IIgsMidi(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) { - _data = data; // Save the resource pointer - _ptr = _data + 2; // Set current position to just after the header - _len = len; // Save the resource's length - _type = READ_LE_UINT16(data); // Read sound resource's type - _midiTicks = _soundBufTicks = 0; - _isValid = (_type == AGI_SOUND_MIDI) && (_data != NULL) && (_len >= 2); - - if (!_isValid) // Check for errors - warning("Error creating Apple IIGS midi sound from resource %d (Type %d, length %d)", resnum, _type, len); -} - PCjrSound::PCjrSound(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) { _data = data; // Save the resource pointer _len = len; // Save the resource's length @@ -86,247 +76,12 @@ const uint8 *PCjrSound::getVoicePointer(uint voiceNum) { return _data + voiceStartOffset; } -IIgsSample::IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) { - Common::MemoryReadStream stream(data, len, DisposeAfterUse::YES); - - // Check that the header was read ok and that it's of the correct type - if (_header.read(stream) && _header.type == AGI_SOUND_SAMPLE) { // An Apple IIGS AGI sample resource - uint32 sampleStartPos = stream.pos(); - uint32 tailLen = stream.size() - sampleStartPos; - - if (tailLen < _header.sampleSize) { // Check if there's no room for the sample data in the stream - // Apple IIGS Manhunter I: Sound resource 16 has only 16074 bytes - // of sample data although header says it should have 16384 bytes. - warning("Apple IIGS sample (%d) too short (%d bytes. Should be %d bytes). Using the part that's left", - resnum, tailLen, _header.sampleSize); - - _header.sampleSize = (uint16) tailLen; // Use the part that's left - } - - if (_header.pitch > 0x7F) { // Check if the pitch is invalid - warning("Apple IIGS sample (%d) has too high pitch (0x%02x)", resnum, _header.pitch); - - _header.pitch &= 0x7F; // Apple IIGS AGI probably did it this way too - } - - // Finalize the header info using the 8-bit unsigned sample data - _header.finalize(stream); - - // Convert sample data from 8-bit unsigned to 8-bit signed format - stream.seek(sampleStartPos); - _sample = new int8[_header.sampleSize]; - - if (_sample != NULL) - _isValid = SoundMgr::convertWave(stream, _sample, _header.sampleSize); - } - - if (!_isValid) // Check for errors - warning("Error creating Apple IIGS sample from resource %d (Type %d, length %d)", resnum, _header.type, len); -} - -/** Reads an Apple IIGS envelope from then given stream. */ -bool IIgsEnvelope::read(Common::SeekableReadStream &stream) { - for (int segNum = 0; segNum < ENVELOPE_SEGMENT_COUNT; segNum++) { - seg[segNum].bp = stream.readByte(); - seg[segNum].inc = stream.readUint16LE(); - } - - return !(stream.eos() || stream.err()); -} - -/** Reads an Apple IIGS wave information structure from the given stream. */ -bool IIgsWaveInfo::read(Common::SeekableReadStream &stream, bool ignoreAddr) { - top = stream.readByte(); - addr = stream.readByte() * 256; - size = (1 << (stream.readByte() & 7)) * 256; - - // Read packed mode byte and parse it into parts - byte packedModeByte = stream.readByte(); - channel = (packedModeByte >> 4) & 1; // Bit 4 - mode = (packedModeByte >> 1) & 3; // Bits 1-2 - halt = (packedModeByte & 1) != 0; // Bit 0 (Converted to boolean) - - relPitch = stream.readSint16LE(); - - // Zero the wave address if we want to ignore the wave address info - if (ignoreAddr) - addr = 0; - - return !(stream.eos() || stream.err()); -} - -bool IIgsWaveInfo::finalize(Common::SeekableReadStream &uint8Wave) { - uint32 startPos = uint8Wave.pos(); // Save stream's starting position - uint8Wave.seek(addr, SEEK_CUR); // Seek to wave's address - - // Calculate the true sample size (A zero ends the sample prematurely) - uint trueSize = size; // Set a default value for the result - for (uint i = 0; i < size; i++) { - if (uint8Wave.readByte() == 0) { - trueSize = i; - // A zero in the sample stream turns off looping - // (At least that's what MESS 0.117 and KEGS32 0.91 seem to do) - if (mode == OSC_MODE_LOOP) - mode = OSC_MODE_ONESHOT; - break; - } - } - size = trueSize; // Set the true sample size - - uint8Wave.seek(startPos); // Seek back to the stream's starting position - - return true; -} - -bool IIgsOscillator::finalize(Common::SeekableReadStream &uint8Wave) { - for (uint i = 0; i < WAVES_PER_OSCILLATOR; i++) - if (!waves[i].finalize(uint8Wave)) - return false; - - return true; -} - -bool IIgsOscillatorList::read(Common::SeekableReadStream &stream, uint oscillatorCount, bool ignoreAddr) { - // First read the A waves and then the B waves for the oscillators - for (uint waveNum = 0; waveNum < WAVES_PER_OSCILLATOR; waveNum++) - for (uint oscNum = 0; oscNum < oscillatorCount; oscNum++) - if (!osc[oscNum].waves[waveNum].read(stream, ignoreAddr)) - return false; - - count = oscillatorCount; // Set the oscillator count - - return true; -} - -bool IIgsOscillatorList::finalize(Common::SeekableReadStream &uint8Wave) { - for (uint i = 0; i < count; i++) - if (!osc[i].finalize(uint8Wave)) - return false; - - return true; -} - -bool IIgsInstrumentHeader::read(Common::SeekableReadStream &stream, bool ignoreAddr) { - env.read(stream); - relseg = stream.readByte(); - /*byte priority =*/ stream.readByte(); // Not needed? 32 in all tested data. - bendrange = stream.readByte(); - vibdepth = stream.readByte(); - vibspeed = stream.readByte(); - /*byte spare =*/ stream.readByte(); // Not needed? 0 in all tested data. - byte wac = stream.readByte(); // Read A wave count - byte wbc = stream.readByte(); // Read B wave count - oscList.read(stream, wac, ignoreAddr); // Read the oscillators - return (wac == wbc) && !(stream.eos() || stream.err()); // A and B wave counts must match -} - -bool IIgsInstrumentHeader::finalize(Common::SeekableReadStream &uint8Wave) { - return oscList.finalize(uint8Wave); -} - -bool IIgsSampleHeader::read(Common::SeekableReadStream &stream) { - type = stream.readUint16LE(); - pitch = stream.readByte(); - unknownByte_Ofs3 = stream.readByte(); - volume = stream.readByte(); - unknownByte_Ofs5 = stream.readByte(); - instrumentSize = stream.readUint16LE(); - sampleSize = stream.readUint16LE(); - // Read the instrument header *ignoring* its wave address info - - return instrument.read(stream, true); -} - -bool IIgsSampleHeader::finalize(Common::SeekableReadStream &uint8Wave) { - return instrument.finalize(uint8Wave); -} - -/** Older Apple IIGS AGI MIDI program change to instrument number mapping. */ -static const MidiProgramChangeMapping progToInstMappingV1 = { - {19, 20, 22, 23, 21, 24, 5, 5, 5, 5, - 6, 7, 10, 9, 11, 9, 15, 8, 5, 5, - 17, 16, 18, 12, 14, 5, 5, 5, 5, 5, - 0, 1, 2, 9, 3, 4, 15, 2, 2, 2, - 25, 13, 13, 25}, - 5 -}; - -/** Newer Apple IIGS AGI MIDI program change to instrument number mapping. */ -static const MidiProgramChangeMapping progToInstMappingV2 = { - {21, 22, 24, 25, 23, 26, 6, 6, 6, 6, - 7, 9, 12, 8, 13, 11, 17, 10, 6, 6, - 19, 18, 20, 14, 16, 6, 6, 6, 6, 6, - 0, 1, 2, 4, 3, 5, 17, 2, 2, 2, - 27, 15, 15, 27}, - 6 -}; - -/** Older Apple IIGS AGI instrument set. Used only by Space Quest I (AGI v1.002). */ -static const InstrumentSetInfo instSetV1 = { - 1192, 26, "7ee16bbc135171ffd6b9120cc7ff1af2", "edd3bf8905d9c238e02832b732fb2e18", progToInstMappingV1 -}; - -/** Newer Apple IIGS AGI instrument set (AGI v1.003+). Used by all others than Space Quest I. */ -static const InstrumentSetInfo instSetV2 = { - 1292, 28, "b7d428955bb90721996de1cbca25e768", "c05fb0b0e11deefab58bc68fbd2a3d07", progToInstMappingV2 -}; - -/** Information about different Apple IIGS AGI executables. */ -static const IIgsExeInfo IIgsExeInfos[] = { - {GID_SQ1, "SQ", 0x1002, 138496, 0x80AD, instSetV1}, - {GID_LSL1, "LL", 0x1003, 141003, 0x844E, instSetV2}, - {GID_AGIDEMO, "DEMO", 0x1005, 141884, 0x8469, instSetV2}, - {GID_KQ1, "KQ", 0x1006, 141894, 0x8469, instSetV2}, - {GID_PQ1, "PQ", 0x1007, 141882, 0x8469, instSetV2}, - {GID_MIXEDUP, "MG", 0x1013, 142552, 0x84B7, instSetV2}, - {GID_KQ2, "KQ2", 0x1013, 143775, 0x84B7, instSetV2}, - {GID_KQ3, "KQ3", 0x1014, 144312, 0x84B7, instSetV2}, - {GID_SQ2, "SQ2", 0x1014, 107882, 0x6563, instSetV2}, - {GID_MH1, "MH", 0x2004, 147678, 0x8979, instSetV2}, - {GID_KQ4, "KQ4", 0x2006, 147652, 0x8979, instSetV2}, - {GID_BC, "BC", 0x3001, 148192, 0x8979, instSetV2}, - {GID_GOLDRUSH, "GR", 0x3003, 148268, 0x8979, instSetV2} -}; - -static const int16 waveformRamp[WAVEFORM_SIZE] = { - 0, 8, 16, 24, 32, 40, 48, 56, - 64, 72, 80, 88, 96, 104, 112, 120, - 128, 136, 144, 152, 160, 168, 176, 184, - 192, 200, 208, 216, 224, 232, 240, 255, - 0, -248, -240, -232, -224, -216, -208, -200, - -192, -184, -176, -168, -160, -152, -144, -136, - -128, -120, -112, -104, -96, -88, -80, -72, - -64, -56, -48, -40, -32, -24, -16, -8 // Ramp up -}; - -static const int16 waveformSquare[WAVEFORM_SIZE] = { - 255, 230, 220, 220, 220, 220, 220, 220, - 220, 220, 220, 220, 220, 220, 220, 220, - 220, 220, 220, 220, 220, 220, 220, 220, - 220, 220, 220, 220, 220, 220, 220, 110, - -255, -230, -220, -220, -220, -220, -220, -220, - -220, -220, -220, -220, -220, -220, -220, -220, - -220, -220, -220, -220, -220, -220, -220, -220, - -220, -220, -220, -110, 0, 0, 0, 0 // Square -}; - -static const int16 waveformMac[WAVEFORM_SIZE] = { - 45, 110, 135, 161, 167, 173, 175, 176, - 156, 137, 123, 110, 91, 72, 35, -2, - -60, -118, -142, -165, -170, -176, -177, -179, - -177, -176, -164, -152, -117, -82, -17, 47, - 92, 137, 151, 166, 170, 173, 171, 169, - 151, 133, 116, 100, 72, 43, -7, -57, - -99, -141, -156, -170, -174, -177, -178, -179, - -175, -172, -165, -159, -137, -114, -67, -19 -}; - +#if 0 static const uint16 period[] = { 1024, 1085, 1149, 1218, 1290, 1367, 1448, 1534, 1625, 1722, 1825, 1933 }; -#if 0 static int noteToPeriod(int note) { return 10 * (period[note % 12] >> (note / 12 - 3)); } @@ -346,8 +101,7 @@ void SoundMgr::unloadSound(int resnum) { } void SoundMgr::startSound(int resnum, int flag) { - int i; - AgiSoundType type; + AgiSoundEmuType type; if (_vm->_game.sounds[resnum] != NULL && _vm->_game.sounds[resnum]->isPlaying()) return; @@ -357,7 +111,7 @@ void SoundMgr::startSound(int resnum, int flag) { if (_vm->_game.sounds[resnum] == NULL) // Is this needed at all? return; - type = (AgiSoundType)_vm->_game.sounds[resnum]->type(); + type = (AgiSoundEmuType)_vm->_game.sounds[resnum]->type(); if (type != AGI_SOUND_SAMPLE && type != AGI_SOUND_MIDI && type != AGI_SOUND_4CHN) return; @@ -367,39 +121,8 @@ void SoundMgr::startSound(int resnum, int flag) { debugC(3, kDebugLevelSound, "startSound(resnum = %d, flag = %d) type = %d", resnum, flag, type); - switch (type) { - case AGI_SOUND_SAMPLE: { - IIgsSample *sampleRes = (IIgsSample *) _vm->_game.sounds[_playingSound]; - _gsSound.playSampleSound(sampleRes->getHeader(), sampleRes->getSample()); - break; - } - case AGI_SOUND_MIDI: - ((IIgsMidi *) _vm->_game.sounds[_playingSound])->rewind(); - break; - case AGI_SOUND_4CHN: - PCjrSound *pcjrSound = (PCjrSound *) _vm->_game.sounds[resnum]; - - // Initialize channel info - for (i = 0; i < NUM_CHANNELS; i++) { - _chn[i].type = type; - _chn[i].flags = AGI_SOUND_LOOP; - - if (_env) { - _chn[i].flags |= AGI_SOUND_ENVELOPE; - _chn[i].adsr = AGI_SOUND_ENV_ATTACK; - } - - _chn[i].ins = _waveform; - _chn[i].size = WAVEFORM_SIZE; - _chn[i].ptr = pcjrSound->getVoicePointer(i % 4); - _chn[i].timer = 0; - _chn[i].vol = 0; - _chn[i].end = 0; - } - break; - } + _soundGen->play(resnum); - memset(_sndBuffer, 0, BUFFER_SIZE << 1); _endflag = flag; // Nat Budin reports that the flag should be reset when sound starts @@ -407,907 +130,68 @@ void SoundMgr::startSound(int resnum, int flag) { } void SoundMgr::stopSound() { - int i; - debugC(3, kDebugLevelSound, "stopSound() --> %d", _playingSound); _endflag = -1; - if (_vm->_soundemu != SOUND_EMU_APPLE2GS) { - for (i = 0; i < NUM_CHANNELS; i++) - stopNote(i); - } if (_playingSound != -1) { if (_vm->_game.sounds[_playingSound]) // sanity checking _vm->_game.sounds[_playingSound]->stop(); - if (_vm->_soundemu == SOUND_EMU_APPLE2GS) { - _gsSound.stopSounds(); - } + _soundGen->stop(); _playingSound = -1; } -} -void IIgsSoundMgr::stopSounds() { - // Stops all sounds on all MIDI channels - for (iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter) - iter->stopSounds(); + if (_endflag != -1) + _vm->setflag(_endflag, true); } -bool IIgsSoundMgr::playSampleSound(const IIgsSampleHeader &sampleHeader, const int8 *sample) { - stopSounds(); - IIgsMidiChannel &channel = _midiChannels[kSfxMidiChannel]; +int SoundMgr::initSound() { + return -1; +} - channel.setInstrument(&sampleHeader.instrument, sample); - channel.setVolume(sampleHeader.volume); - channel.noteOn(sampleHeader.pitch, 64); // Use default velocity (i.e. 64) +void SoundMgr::deinitSound() { + stopSound(); - return true; + delete _soundGen; } -void IIgsMidiChannel::stopSounds() { - // Stops all sounds on this single MIDI channel - for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) - iter->stop(); +void SoundMgr::soundIsFinished() { + if (_endflag != -1) + _vm->setflag(_endflag, true); - _gsChannels.clear(); + if (_playingSound != -1) + _vm->_game.sounds[_playingSound]->stop(); + _playingSound = -1; + _endflag = -1; } -int SoundMgr::initSound() { - int r = -1; - - memset(_sndBuffer, 0, BUFFER_SIZE << 1); - _env = false; +SoundMgr::SoundMgr(AgiEngine *agi, Audio::Mixer *pMixer) { + _vm = agi; + _endflag = -1; + _playingSound = -1; switch (_vm->_soundemu) { case SOUND_EMU_NONE: - _waveform = waveformRamp; - _env = true; - break; case SOUND_EMU_AMIGA: - case SOUND_EMU_PC: - _waveform = waveformSquare; - break; case SOUND_EMU_MAC: - _waveform = waveformMac; + _soundGen = new SoundGenSarien(_vm, pMixer); + break; + case SOUND_EMU_PC: + case SOUND_EMU_PCJR: + _soundGen = new SoundGenPCJr(_vm, pMixer); break; case SOUND_EMU_APPLE2GS: - _disabledMidi = !loadInstruments(); + _soundGen = new SoundGen2GS(_vm, pMixer); break; case SOUND_EMU_COCO3: + _soundGen = new SoundGenCoCo3(_vm, pMixer); break; - } - - report("Initializing sound:\n"); - - report("sound: envelopes "); - if (_env) { - report("enabled (decay=%d, sustain=%d)\n", ENV_DECAY, ENV_SUSTAIN); - } else { - report("disabled\n"); - } - - _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); - - return r; -} - -void SoundMgr::deinitSound() { - debugC(3, kDebugLevelSound, "()"); - - _mixer->stopHandle(_soundHandle); -} - -void SoundMgr::stopNote(int i) { - _chn[i].adsr = AGI_SOUND_ENV_RELEASE; - - if (_useChorus) { - // Stop chorus ;) - if (_chn[i].type == AGI_SOUND_4CHN && - _vm->_soundemu == SOUND_EMU_NONE && i < 3) { - stopNote(i + 4); - } - } -} - -void SoundMgr::playNote(int i, int freq, int vol) { - if (!_vm->getflag(fSoundOn)) - vol = 0; - else if (vol && _vm->_soundemu == SOUND_EMU_PC) - vol = 160; - - _chn[i].phase = 0; - _chn[i].freq = freq; - _chn[i].vol = vol; - _chn[i].env = 0x10000; - _chn[i].adsr = AGI_SOUND_ENV_ATTACK; - - if (_useChorus) { - // Add chorus ;) - if (_chn[i].type == AGI_SOUND_4CHN && - _vm->_soundemu == SOUND_EMU_NONE && i < 3) { - - int newfreq = freq * 1007 / 1000; - - if (freq == newfreq) - newfreq++; - - playNote(i + 4, newfreq, vol * 2 / 3); - } - } -} - -void SoundMgr::playMidiSound() { - if (_disabledMidi) - return; - - const uint8 *p; - uint8 parm1, parm2; - static uint8 cmd, ch; - - if (_playingSound == -1 || _vm->_game.sounds[_playingSound] == NULL) { - warning("Error playing Apple IIGS MIDI sound resource"); - _playing = false; - - return; - } - - IIgsMidi *midiObj = (IIgsMidi *) _vm->_game.sounds[_playingSound]; - - _playing = true; - p = midiObj->getPtr(); - - midiObj->_soundBufTicks++; - - while (true) { - uint8 readByte = *p; - - // Check for end of MIDI sequence marker (Can also be here before delta-time) - if (readByte == MIDI_BYTE_STOP_SEQUENCE) { - debugC(3, kDebugLevelSound, "End of MIDI sequence (Before reading delta-time)"); - _playing = false; - - midiObj->rewind(); - - return; - } else if (readByte == MIDI_BYTE_TIMER_SYNC) { - debugC(3, kDebugLevelSound, "Timer sync"); - p++; // Jump over the timer sync byte as it's not needed - - continue; - } - - uint8 deltaTime = readByte; - if (midiObj->_midiTicks + deltaTime > midiObj->_soundBufTicks) { - break; - } - midiObj->_midiTicks += deltaTime; - p++; // Jump over the delta-time byte as it was already taken care of - - // Check for end of MIDI sequence marker (This time it after reading delta-time) - if (*p == MIDI_BYTE_STOP_SEQUENCE) { - debugC(3, kDebugLevelSound, "End of MIDI sequence (After reading delta-time)"); - _playing = false; - - midiObj->rewind(); - - return; - } - - // Separate byte into command and channel if it's a command byte. - // Otherwise use running status (i.e. previously set command and channel). - if (*p & 0x80) { - cmd = *p++; - ch = cmd & 0x0f; - cmd >>= 4; - } - - switch (cmd) { - case MIDI_CMD_NOTE_OFF: - parm1 = *p++; - parm2 = *p++; - _gsSound.midiNoteOff(ch, parm1, parm2); - break; - case MIDI_CMD_NOTE_ON: - parm1 = *p++; - parm2 = *p++; - _gsSound.midiNoteOn(ch, parm1, parm2); - break; - case MIDI_CMD_CONTROLLER: - parm1 = *p++; - parm2 = *p++; - _gsSound.midiController(ch, parm1, parm2); - break; - case MIDI_CMD_PROGRAM_CHANGE: - parm1 = *p++; - _gsSound.midiProgramChange(ch, parm1); - break; - case MIDI_CMD_PITCH_WHEEL: - parm1 = *p++; - parm2 = *p++; - - uint16 wheelPos = ((parm2 & 0x7F) << 7) | (parm1 & 0x7F); // 14-bit value - _gsSound.midiPitchWheel(wheelPos); - break; - } - } - - midiObj->setPtr(p); -} - -void IIgsSoundMgr::midiNoteOff(uint8 channel, uint8 note, uint8 velocity) { - _midiChannels[channel].noteOff(note, velocity); - debugC(3, kDebugLevelSound, "note off, channel %02x, note %02x, velocity %02x", channel, note, velocity); -} - -void IIgsSoundMgr::midiNoteOn(uint8 channel, uint8 note, uint8 velocity) { - _midiChannels[channel].noteOn(note, velocity); - debugC(3, kDebugLevelSound, "note on, channel %02x, note %02x, velocity %02x", channel, note, velocity); -} - -// TODO: Check if controllers behave differently on different MIDI channels -// TODO: Doublecheck what other controllers than the volume controller do -void IIgsSoundMgr::midiController(uint8 channel, uint8 controller, uint8 value) { - IIgsMidiChannel &midiChannel = _midiChannels[channel]; - - // The tested Apple IIGS AGI MIDI resources only used - // controllers 0 (Bank select?), 7 (Volume) and 64 (Sustain On/Off). - // Controller 0's parameter was in range 94-127, - // controller 7's parameter was in range 0-127 and - // controller 64's parameter was always 0 (i.e. sustain off). - bool unimplemented = false; - switch (controller) { - case 7: // Volume - midiChannel.setVolume(value); - break; - default: - unimplemented = true; + case SOUND_EMU_MIDI: + _soundGen = new SoundGenMIDI(_vm, pMixer); break; } - debugC(3, kDebugLevelSound, "controller %02x, ch %02x, val %02x%s", controller, channel, value, unimplemented ? " (Unimplemented)" : ""); -} - -void IIgsSoundMgr::midiProgramChange(uint8 channel, uint8 program) { - _midiChannels[channel].setInstrument(getInstrument(program), _wave.begin()); - debugC(3, kDebugLevelSound, "program change %02x, channel %02x", program, channel); -} - -void IIgsSoundMgr::midiPitchWheel(uint8 wheelPos) { - // In all the tested Apple IIGS AGI MIDI resources - // pitch wheel commands always used 0x2000 (Center position). - // Therefore it should be quite safe to ignore this command. - debugC(3, kDebugLevelSound, "pitch wheel position %04x (Unimplemented)", wheelPos); -} - -IIgsSoundMgr::IIgsSoundMgr() { - _midiChannels.resize(16); // Set the amount of available MIDI channels -} - -const IIgsInstrumentHeader* IIgsSoundMgr::getInstrument(uint8 program) const { - return &_instruments[_midiProgToInst->map(program)]; -} - -void IIgsSoundMgr::setProgramChangeMapping(const MidiProgramChangeMapping *mapping) { - _midiProgToInst = mapping; -} - -void IIgsSoundMgr::removeStoppedSounds() { - for (Common::Array<IIgsMidiChannel>::iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter) - iter->removeStoppedSounds(); -} - -void IIgsMidiChannel::removeStoppedSounds() { - for (int i = _gsChannels.size() - 1; i >= 0; i--) - if (!_gsChannels[i].playing()) - _gsChannels.remove_at(i); -} - -uint IIgsSoundMgr::activeSounds() const { - uint result = 0; - - for (Common::Array<IIgsMidiChannel>::const_iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter) - result += iter->activeSounds(); - - return result; -} - -uint IIgsMidiChannel::activeSounds() const { - uint result = 0; - - for (const_iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) - if (!iter->end) - result++; - - return result; -} - -void IIgsMidiChannel::setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample) { - _instrument = instrument; - _sample = sample; - - // Set program on each Apple IIGS channel playing on this MIDI channel - for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) - iter->setInstrument(instrument, sample); -} - -void IIgsMidiChannel::setVolume(uint8 volume) { - _volume = volume; - - // Set volume on each Apple IIGS channel playing on this MIDI channel - for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) - iter->setChannelVolume(volume); -} - -void IIgsMidiChannel::noteOff(uint8 note, uint8 velocity) { - // Go through all the notes playing on this MIDI channel - // and turn off the ones that are playing the given note - for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) - if (iter->origNote == note) - iter->noteOff(velocity); -} - -void IIgsMidiChannel::noteOn(uint8 note, uint8 velocity) { - IIgsChannelInfo channel; - - // Use the default channel volume and instrument - channel.setChannelVolume(_volume); - channel.setInstrument(_instrument, _sample); - - // Set the note on and save the channel - channel.noteOn(note, velocity); - _gsChannels.push_back(channel); -} - -void IIgsChannelInfo::rewind() { - this->envVol = this->startEnvVol; - this->envSeg = 0; - this->pos = intToFrac(0); -} - -void IIgsChannelInfo::setChannelVolume(uint8 volume) { - this->chanVol = intToFrac(volume); -} - -void IIgsChannelInfo::setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample) { - assert(instrument != NULL && sample != NULL); - this->ins = instrument; - this->unrelocatedSample = sample; -} - -// TODO/FIXME: Implement correctly and fully (Take velocity into account etc) -void IIgsChannelInfo::noteOn(uint8 noteParam, uint8 velocity) { - this->origNote = noteParam; - this->startEnvVol = intToFrac(0); - rewind(); - - const IIgsWaveInfo *waveInfo = NULL; - - for (uint i = 0; i < ins->oscList.count; i++) - if (ins->oscList(i).waves[0].top >= noteParam) - waveInfo = &ins->oscList(i).waves[0]; - - assert(waveInfo != NULL); - - this->relocatedSample = this->unrelocatedSample + waveInfo->addr; - this->posAdd = intToFrac(0); - this->note = intToFrac(noteParam) + doubleToFrac(waveInfo->relPitch/256.0); - this->vol = doubleToFrac(fracToDouble(this->envVol) * fracToDouble(this->chanVol) / 127.0); - this->loop = (waveInfo->mode == OSC_MODE_LOOP); - this->size = waveInfo->size - waveInfo->addr; - this->end = waveInfo->halt; -} - -// TODO/FIXME: Implement correctly and fully (Take release time and velocity into account etc) -void IIgsChannelInfo::noteOff(uint8 velocity) { - this->loop = false; - this->envSeg = ins->relseg; -} - -void IIgsChannelInfo::stop() { - this->end = true; -} - -bool IIgsChannelInfo::playing() { - return !this->end; -} - -void SoundMgr::playSampleSound() { - if (_vm->_soundemu != SOUND_EMU_APPLE2GS) { - warning("Trying to play a sample but not using Apple IIGS sound emulation mode"); - return; - } - - if (_playingSound != -1) - _playing = _gsSound.activeSounds() > 0; -} - -static int cocoFrequencies[] = { - 130, 138, 146, 155, 164, 174, 184, 195, 207, 220, 233, 246, - 261, 277, 293, 311, 329, 349, 369, 391, 415, 440, 466, 493, - 523, 554, 587, 622, 659, 698, 739, 783, 830, 880, 932, 987, - 1046, 1108, 1174, 1244, 1318, 1396, 1479, 1567, 1661, 1760, 1864, 1975, - 2093, 2217, 2349, 2489, 2637, 2793, 2959, 3135, 3322, 3520, 3729, 3951 -}; - -void SoundMgr::playCoCoSound() { - int i = 0; - CoCoNote note; - - do { - note.read(_chn[i].ptr); - - if (note.freq != 0xff) { - playNote(0, cocoFrequencies[note.freq], note.volume); - - uint32 start_time = _vm->_system->getMillis(); - - while (_vm->_system->getMillis() < start_time + note.duration) { - _vm->_system->updateScreen(); - - _vm->_system->delayMillis(10); - } - } - } while (note.freq != 0xff); -} - -void SoundMgr::playAgiSound() { - int i; - AgiNote note; - - _playing = false; - for (i = 0; i < (_vm->_soundemu == SOUND_EMU_PC ? 1 : 4); i++) { - _playing |= !_chn[i].end; - note.read(_chn[i].ptr); // Read a single note (Doesn't advance the pointer) - - if (_chn[i].end) - continue; - - if ((--_chn[i].timer) <= 0) { - stopNote(i); - - if (note.freqDiv != 0) { - int volume = (note.attenuation == 0x0F) ? 0 : (0xFF - note.attenuation * 2); - playNote(i, note.freqDiv * 10, volume); - } - - _chn[i].timer = note.duration; - - if (_chn[i].timer == 0xffff) { - _chn[i].end = 1; - _chn[i].vol = 0; - _chn[i].env = 0; - - if (_useChorus) { - // chorus - if (_chn[i].type == AGI_SOUND_4CHN && _vm->_soundemu == SOUND_EMU_NONE && i < 3) { - _chn[i + 4].vol = 0; - _chn[i + 4].env = 0; - } - } - } - _chn[i].ptr += 5; // Advance the pointer to the next note data (5 bytes per note) - } - } -} - -void SoundMgr::playSound() { - int i; - - if (_endflag == -1) - return; - - if (_vm->_soundemu == SOUND_EMU_APPLE2GS) { - if (_playingSound != -1) { - if (_vm->_game.sounds[_playingSound]->type() == AGI_SOUND_MIDI) { - playMidiSound(); - //warning("playSound: Trying to play an Apple IIGS MIDI sound. Not yet implemented"); - } else if (_vm->_game.sounds[_playingSound]->type() == AGI_SOUND_SAMPLE) { - //debugC(3, kDebugLevelSound, "playSound: Trying to play an Apple IIGS sample"); - playSampleSound(); - } - } - } else if (_vm->_soundemu == SOUND_EMU_COCO3) { - playCoCoSound(); - } else { - //debugC(3, kDebugLevelSound, "playSound: Trying to play a PCjr 4-channel sound"); - playAgiSound(); - } - - if (!_playing) { - if (_vm->_soundemu != SOUND_EMU_APPLE2GS) { - for (i = 0; i < NUM_CHANNELS; _chn[i++].vol = 0) - ; - } - - if (_endflag != -1) - _vm->setflag(_endflag, true); - - if (_playingSound != -1) - _vm->_game.sounds[_playingSound]->stop(); - _playingSound = -1; - _endflag = -1; - } -} - -uint32 SoundMgr::mixSound() { - register int i, p; - const int16 *src; - int c, b, m; - - memset(_sndBuffer, 0, BUFFER_SIZE << 1); - - if (!_playing || _playingSound == -1) - return BUFFER_SIZE; - - // Handle Apple IIGS sound mixing here - // TODO: Implement playing both waves in an oscillator - // TODO: Implement swap-mode in an oscillator - if (_vm->_soundemu == SOUND_EMU_APPLE2GS) { - for (uint midiChan = 0; midiChan < _gsSound._midiChannels.size(); midiChan++) { - for (uint gsChan = 0; gsChan < _gsSound._midiChannels[midiChan]._gsChannels.size(); gsChan++) { - IIgsChannelInfo &channel = _gsSound._midiChannels[midiChan]._gsChannels[gsChan]; - if (channel.playing()) { // Only mix in actively playing channels - // Frequency multiplier was 1076.0 based on tests made with MESS 0.117. - // Tests made with KEGS32 averaged the multiplier to around 1045. - // So this is a guess but maybe it's 1046.5... i.e. C6's frequency? - double hertz = C6_FREQ * pow(SEMITONE, fracToDouble(channel.note)); - channel.posAdd = doubleToFrac(hertz / getRate()); - channel.vol = doubleToFrac(fracToDouble(channel.envVol) * fracToDouble(channel.chanVol) / 127.0); - double tempVol = fracToDouble(channel.vol)/127.0; - for (i = 0; i < IIGS_BUFFER_SIZE; i++) { - b = channel.relocatedSample[fracToInt(channel.pos)]; - // TODO: Find out what volume/amplification setting is loud enough - // but still doesn't clip when playing many channels on it. - _sndBuffer[i] += (int16) (b * tempVol * 256/4); - channel.pos += channel.posAdd; - - if (channel.pos >= intToFrac(channel.size)) { - if (channel.loop) { - // Don't divide by zero on zero length samples - channel.pos %= intToFrac(channel.size + (channel.size == 0)); - // Probably we should loop the envelope too - channel.envSeg = 0; - channel.envVol = channel.startEnvVol; - } else { - channel.pos = channel.chanVol = 0; - channel.end = true; - break; - } - } - } - - if (channel.envSeg < ENVELOPE_SEGMENT_COUNT) { - const IIgsEnvelopeSegment &seg = channel.ins->env.seg[channel.envSeg]; - // I currently assume enveloping works with the same speed as the MIDI - // (i.e. with 1/60ths of a second ticks). - // TODO: Check if enveloping really works with the same speed as MIDI - frac_t envVolDelta = doubleToFrac(seg.inc/256.0); - if (intToFrac(seg.bp) >= channel.envVol) { - channel.envVol += envVolDelta; - if (channel.envVol >= intToFrac(seg.bp)) { - channel.envVol = intToFrac(seg.bp); - channel.envSeg += 1; - } - } else { - channel.envVol -= envVolDelta; - if (channel.envVol <= intToFrac(seg.bp)) { - channel.envVol = intToFrac(seg.bp); - channel.envSeg += 1; - } - } - } - } - } - } - _gsSound.removeStoppedSounds(); - return IIGS_BUFFER_SIZE; - } // else ... - - // Handle PCjr 4-channel sound mixing here - for (c = 0; c < NUM_CHANNELS; c++) { - if (!_chn[c].vol) - continue; - - m = _chn[c].flags & AGI_SOUND_ENVELOPE ? - _chn[c].vol * _chn[c].env >> 16 : _chn[c].vol; - - if (_chn[c].type != AGI_SOUND_4CHN || c != 3) { - src = _chn[c].ins; - - p = _chn[c].phase; - for (i = 0; i < BUFFER_SIZE; i++) { - b = src[p >> 8]; -#ifdef USE_INTERPOLATION - b += ((src[((p >> 8) + 1) % _chn[c].size] - src[p >> 8]) * (p & 0xff)) >> 8; -#endif - _sndBuffer[i] += (b * m) >> 4; - - p += (uint32) 118600 *4 / _chn[c].freq; - - // FIXME: Fingolfin asks: why is there a FIXME here? Please either clarify what - // needs fixing, or remove it! - // FIXME - if (_chn[c].flags & AGI_SOUND_LOOP) { - p %= _chn[c].size << 8; - } else { - if (p >= _chn[c].size << 8) { - p = _chn[c].vol = 0; - _chn[c].end = 1; - break; - } - } - - } - _chn[c].phase = p; - } else { - // Add white noise - for (i = 0; i < BUFFER_SIZE; i++) { - b = _vm->_rnd->getRandomNumber(255) - 128; - _sndBuffer[i] += (b * m) >> 4; - } - } - - switch (_chn[c].adsr) { - case AGI_SOUND_ENV_ATTACK: - // not implemented - _chn[c].adsr = AGI_SOUND_ENV_DECAY; - break; - case AGI_SOUND_ENV_DECAY: - if (_chn[c].env > _chn[c].vol * ENV_SUSTAIN + ENV_DECAY) { - _chn[c].env -= ENV_DECAY; - } else { - _chn[c].env = _chn[c].vol * ENV_SUSTAIN; - _chn[c].adsr = AGI_SOUND_ENV_SUSTAIN; - } - break; - case AGI_SOUND_ENV_SUSTAIN: - break; - case AGI_SOUND_ENV_RELEASE: - if (_chn[c].env >= ENV_RELEASE) { - _chn[c].env -= ENV_RELEASE; - } else { - _chn[c].env = 0; - } - } - } - - return BUFFER_SIZE; -} - -/** - * Finds information about an Apple IIGS AGI executable based on the game ID. - * @return A non-null IIgsExeInfo pointer if successful, otherwise NULL. - */ -const IIgsExeInfo *SoundMgr::getIIgsExeInfo(enum AgiGameID gameid) const { - for (int i = 0; i < ARRAYSIZE(IIgsExeInfos); i++) - if (IIgsExeInfos[i].gameid == gameid) - return &IIgsExeInfos[i]; - return NULL; -} - -bool IIgsSoundMgr::loadInstrumentHeaders(const Common::FSNode &exePath, const IIgsExeInfo &exeInfo) { - bool loadedOk = false; // Was loading successful? - Common::File file; - - // Open the executable file and check that it has correct size - file.open(exePath); - if (file.size() != (int32)exeInfo.exeSize) { - debugC(3, kDebugLevelSound, "Apple IIGS executable (%s) has wrong size (Is %d, should be %d)", - exePath.getPath().c_str(), file.size(), exeInfo.exeSize); - } - - // Read the whole executable file into memory - Common::SharedPtr<Common::MemoryReadStream> data(file.readStream(file.size())); - file.close(); - - // Check that we got enough data to be able to parse the instruments - if (data && data->size() >= (int32)(exeInfo.instSetStart + exeInfo.instSet.byteCount)) { - // Check instrument set's length (The info's saved in the executable) - data->seek(exeInfo.instSetStart - 4); - uint16 instSetByteCount = data->readUint16LE(); - if (instSetByteCount != exeInfo.instSet.byteCount) { - debugC(3, kDebugLevelSound, "Wrong instrument set size (Is %d, should be %d) in Apple IIGS executable (%s)", - instSetByteCount, exeInfo.instSet.byteCount, exePath.getPath().c_str()); - } - - // Check instrument set's md5sum - data->seek(exeInfo.instSetStart); - - char md5str[32+1]; - Common::md5_file_string(*data, md5str, exeInfo.instSet.byteCount); - if (scumm_stricmp(md5str, exeInfo.instSet.md5)) { - warning("Unknown Apple IIGS instrument set (md5: %s) in %s, trying to use it nonetheless", - md5str, exePath.getPath().c_str()); - } - - // Read in the instrument set one instrument at a time - data->seek(exeInfo.instSetStart); - - // Load the instruments - _instruments.clear(); - _instruments.reserve(exeInfo.instSet.instCount); - - IIgsInstrumentHeader instrument; - for (uint i = 0; i < exeInfo.instSet.instCount; i++) { - if (!instrument.read(*data)) { - warning("Error loading Apple IIGS instrument (%d. of %d) from %s, not loading more instruments", - i + 1, exeInfo.instSet.instCount, exePath.getPath().c_str()); - break; - } - _instruments.push_back(instrument); // Add the successfully loaded instrument to the instruments array - } - - // Loading was successful only if all instruments were loaded successfully - loadedOk = (_instruments.size() == exeInfo.instSet.instCount); - } else // Couldn't read enough data from the executable file - warning("Error loading instruments from Apple IIGS executable (%s)", exePath.getPath().c_str()); - - return loadedOk; -} - -/** - * Convert sample from 8-bit unsigned to 8-bit signed format. - * @param source Source stream containing the 8-bit unsigned sample data. - * @param dest Destination buffer for the 8-bit signed sample data. - * @param length Length of the sample data to be converted. - */ -bool SoundMgr::convertWave(Common::SeekableReadStream &source, int8 *dest, uint length) { - // Convert the wave from 8-bit unsigned to 8-bit signed format - for (uint i = 0; i < length; i++) - dest[i] = (int8) ((int) source.readByte() - 128); - return !(source.eos() || source.err()); -} - -bool IIgsSoundMgr::loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo &exeInfo) { - Common::File file; - - // Open the wave file and read it into memory - file.open(wavePath); - Common::SharedPtr<Common::MemoryReadStream> uint8Wave(file.readStream(file.size())); - file.close(); - - // Check that we got the whole wave file - if (uint8Wave && uint8Wave->size() == SIERRASTANDARD_SIZE) { - // Check wave file's md5sum - char md5str[32+1]; - Common::md5_file_string(*uint8Wave, md5str, SIERRASTANDARD_SIZE); - if (scumm_stricmp(md5str, exeInfo.instSet.waveFileMd5)) { - warning("Unknown Apple IIGS wave file (md5: %s, game: %s).\n" \ - "Please report the information on the previous line to the ScummVM team.\n" \ - "Using the wave file as it is - music may sound weird", md5str, exeInfo.exePrefix); - } - - uint8Wave->seek(0); // Seek wave to its start - // Convert the wave file from 8-bit unsigned to 8-bit signed and save the result - _wave.resize(uint8Wave->size()); - return SoundMgr::convertWave(*uint8Wave, _wave.begin(), uint8Wave->size()); - } else { // Couldn't read the wave file or it had incorrect size - warning("Error loading Apple IIGS wave file (%s), not loading instruments", wavePath.getPath().c_str()); - return false; - } -} - -/** - * A function object (i.e. a functor) for testing if a Common::FSNode - * object's name is equal (Ignoring case) to a string or to at least - * one of the strings in a list of strings. Can be used e.g. with find_if(). - */ -struct fsnodeNameEqualsIgnoreCase : public Common::UnaryFunction<const Common::FSNode&, bool> { -// FIXME: This should be replaced; use SearchMan instead - fsnodeNameEqualsIgnoreCase(const Common::StringArray &str) : _str(str) {} - fsnodeNameEqualsIgnoreCase(const Common::String str) { _str.push_back(str); } - bool operator()(const Common::FSNode ¶m) const { - for (Common::StringArray::const_iterator iter = _str.begin(); iter != _str.end(); ++iter) - if (param.getName().equalsIgnoreCase(*iter)) - return true; - return false; - } -private: - Common::StringArray _str; -}; - -bool SoundMgr::loadInstruments() { - // Check that the platform is Apple IIGS, as only it uses custom instruments - if (_vm->getPlatform() != Common::kPlatformApple2GS) { - debugC(3, kDebugLevelSound, "Platform isn't Apple IIGS so not loading any instruments"); - return true; - } - - // Get info on the particular Apple IIGS AGI game's executable - const IIgsExeInfo *exeInfo = getIIgsExeInfo((enum AgiGameID) _vm->getGameID()); - if (exeInfo == NULL) { - warning("Unsupported Apple IIGS game, not loading instruments"); - return false; - } - - // List files in the game path - Common::FSList fslist; - Common::FSNode dir(ConfMan.get("path")); - if (!dir.getChildren(fslist, Common::FSNode::kListFilesOnly)) { - warning("Invalid game path (\"%s\"), not loading Apple IIGS instruments", dir.getPath().c_str()); - return false; - } - - // Populate executable filenames list (Long filename and short filename) for searching - Common::StringArray exeNames; - exeNames.push_back(Common::String(exeInfo->exePrefix) + ".SYS16"); - exeNames.push_back(Common::String(exeInfo->exePrefix) + ".SYS"); - - // Populate wave filenames list (Long filename and short filename) for searching - Common::StringArray waveNames; - waveNames.push_back("SIERRASTANDARD"); - waveNames.push_back("SIERRAST"); - - // Search for the executable file and the wave file (i.e. check if any of the filenames match) - Common::FSList::const_iterator exeFsnode, waveFsnode; - exeFsnode = Common::find_if(fslist.begin(), fslist.end(), fsnodeNameEqualsIgnoreCase(exeNames)); - waveFsnode = Common::find_if(fslist.begin(), fslist.end(), fsnodeNameEqualsIgnoreCase(waveNames)); - - // Make sure that we found the executable file - if (exeFsnode == fslist.end()) { - warning("Couldn't find Apple IIGS game executable (%s), not loading instruments", exeNames.begin()->c_str()); - return false; - } - - // Make sure that we found the wave file - if (waveFsnode == fslist.end()) { - warning("Couldn't find Apple IIGS wave file (%s), not loading instruments", waveNames.begin()->c_str()); - return false; - } - - // Set the MIDI program change to instrument number mapping and - // load the instrument headers and their sample data. - // None of the tested SIERRASTANDARD-files have zeroes in them so - // there's no need to check for prematurely ending samples here. - _gsSound.setProgramChangeMapping(&exeInfo->instSet.progToInst); - return _gsSound.loadWaveFile(*waveFsnode, *exeInfo) && _gsSound.loadInstrumentHeaders(*exeFsnode, *exeInfo); -} - -void SoundMgr::fillAudio(void *udata, int16 *stream, uint len) { - SoundMgr *soundMgr = (SoundMgr *)udata; - uint32 p = 0; - - // current number of audio bytes in _sndBuffer - static uint32 data_available = 0; - // offset of start of audio bytes in _sndBuffer - static uint32 data_offset = 0; - - len <<= 2; - - debugC(5, kDebugLevelSound, "(%p, %p, %d)", (void *)udata, (void *)stream, len); - - while (len > data_available) { - memcpy((uint8 *)stream + p, (uint8*)_sndBuffer + data_offset, data_available); - p += data_available; - len -= data_available; - - soundMgr->playSound(); - data_available = soundMgr->mixSound() << 1; - data_offset = 0; - } - - memcpy((uint8 *)stream + p, (uint8*)_sndBuffer + data_offset, len); - data_offset += len; - data_available -= len; -} - -SoundMgr::SoundMgr(AgiBase *agi, Audio::Mixer *pMixer) : _chn() { - _vm = agi; - _mixer = pMixer; - _sampleRate = pMixer->getOutputRate(); - _endflag = -1; - _playingSound = -1; - _env = false; - _playing = false; - _sndBuffer = (int16 *)calloc(2, BUFFER_SIZE); - _waveform = 0; - _disabledMidi = false; - _useChorus = true; // FIXME: Currently always true? -} - -void SoundMgr::premixerCall(int16 *data, uint len) { - fillAudio(this, data, len); } void SoundMgr::setVolume(uint8 volume) { @@ -1315,7 +199,6 @@ void SoundMgr::setVolume(uint8 volume) { } SoundMgr::~SoundMgr() { - free(_sndBuffer); } } // End of namespace Agi diff --git a/engines/agi/sound.h b/engines/agi/sound.h index 881e3efd56..63b36e017c 100644 --- a/engines/agi/sound.h +++ b/engines/agi/sound.h @@ -26,160 +26,18 @@ #ifndef AGI_SOUND_H #define AGI_SOUND_H -#include "sound/audiostream.h" #include "sound/mixer.h" -#include "common/frac.h" namespace Agi { -#define BUFFER_SIZE 410 - -// Apple IIGS MIDI uses 60 ticks per second (Based on tests with Apple IIGS -// KQ1 and SQ1 under MESS 0.124a). So we make the audio buffer size to be a -// 1/60th of a second in length. That should be getSampleRate() / 60 samples -// in length but as getSampleRate() is always 22050 at the moment we just use -// the hardcoded value of 368 (22050/60 = 367.5 which rounds up to 368). -// FIXME: Use getSampleRate() / 60 rather than a hardcoded value -#define IIGS_BUFFER_SIZE 368 - #define SOUND_EMU_NONE 0 #define SOUND_EMU_PC 1 -#define SOUND_EMU_TANDY 2 +#define SOUND_EMU_PCJR 2 #define SOUND_EMU_MAC 3 #define SOUND_EMU_AMIGA 4 #define SOUND_EMU_APPLE2GS 5 #define SOUND_EMU_COCO3 6 - -#define WAVEFORM_SIZE 64 -#define ENV_ATTACK 10000 /**< envelope attack rate */ -#define ENV_DECAY 1000 /**< envelope decay rate */ -#define ENV_SUSTAIN 100 /**< envelope sustain level */ -#define ENV_RELEASE 7500 /**< envelope release rate */ -#define NUM_CHANNELS 7 /**< number of sound channels */ - -// MIDI command values (Shifted right by 4 so they're in the lower nibble) -#define MIDI_CMD_NOTE_OFF 0x08 -#define MIDI_CMD_NOTE_ON 0x09 -#define MIDI_CMD_CONTROLLER 0x0B -#define MIDI_CMD_PROGRAM_CHANGE 0x0C -#define MIDI_CMD_PITCH_WHEEL 0x0E -// Whole MIDI byte values (Command and channel info together) -#define MIDI_BYTE_STOP_SEQUENCE 0xFC -#define MIDI_BYTE_TIMER_SYNC 0xF8 - -struct IIgsEnvelopeSegment { - uint8 bp; - uint16 inc; ///< 8b.8b fixed point, very probably little endian -}; - -#define ENVELOPE_SEGMENT_COUNT 8 -struct IIgsEnvelope { - IIgsEnvelopeSegment seg[ENVELOPE_SEGMENT_COUNT]; - - /** Reads an Apple IIGS envelope from then given stream. */ - bool read(Common::SeekableReadStream &stream); -}; - -// 2**(1/12) i.e. the 12th root of 2 -#define SEMITONE 1.059463094359295 - -// C6's frequency is A4's (440 Hz) frequency but one full octave and three semitones higher -// i.e. C6_FREQ = 440 * pow(2.0, 15/12.0) -#define C6_FREQ 1046.502261202395 - -// Size of the SIERRASTANDARD file (i.e. the wave file i.e. the sample data used by the instruments). -#define SIERRASTANDARD_SIZE 65536 - -// Maximum number of instruments in an Apple IIGS instrument set. -// Chosen empirically based on Apple IIGS AGI game data, increase if needed. -#define MAX_INSTRUMENTS 28 - -struct IIgsWaveInfo { - uint8 top; - uint addr; - uint size; -// Oscillator channel -#define OSC_CHANNEL_RIGHT 0 -#define OSC_CHANNEL_LEFT 1 - uint channel; -// Oscillator mode -#define OSC_MODE_LOOP 0 -#define OSC_MODE_ONESHOT 1 -#define OSC_MODE_SYNC_AM 2 -#define OSC_MODE_SWAP 3 - uint mode; - bool halt; - int16 relPitch; ///< Relative pitch in semitones (Signed 8b.8b fixed point) - - /** Reads an Apple IIGS wave information structure from the given stream. */ - bool read(Common::SeekableReadStream &stream, bool ignoreAddr = false); - bool finalize(Common::SeekableReadStream &uint8Wave); -}; - -// Number of waves per Apple IIGS sound oscillator -#define WAVES_PER_OSCILLATOR 2 - -/** An Apple IIGS sound oscillator. Consists always of two waves. */ -struct IIgsOscillator { - IIgsWaveInfo waves[WAVES_PER_OSCILLATOR]; - - bool finalize(Common::SeekableReadStream &uint8Wave); -}; - -// Maximum number of oscillators in an Apple IIGS instrument. -// Chosen empirically based on Apple IIGS AGI game data, increase if needed. -#define MAX_OSCILLATORS 4 - -/** An Apple IIGS sound oscillator list. */ -struct IIgsOscillatorList { - uint count; ///< Oscillator count - IIgsOscillator osc[MAX_OSCILLATORS]; ///< The oscillators - - /** Indexing operators for easier access to the oscillators. */ - const IIgsOscillator &operator()(uint index) const { return osc[index]; } - IIgsOscillator &operator()(uint index) { return osc[index]; } - - /** Reads an Apple IIGS oscillator list from the given stream. */ - bool read(Common::SeekableReadStream &stream, uint oscillatorCount, bool ignoreAddr = false); - bool finalize(Common::SeekableReadStream &uint8Wave); -}; - -struct IIgsInstrumentHeader { - IIgsEnvelope env; - uint8 relseg; - uint8 bendrange; - uint8 vibdepth; - uint8 vibspeed; - IIgsOscillatorList oscList; - - /** - * Read an Apple IIGS instrument header from the given stream. - * @param stream The source stream from which to read the data. - * @param ignoreAddr Should we ignore wave infos' wave address variable's value? - * @return True if successful, false otherwise. - */ - bool read(Common::SeekableReadStream &stream, bool ignoreAddr = false); - bool finalize(Common::SeekableReadStream &uint8Wave); -}; - -struct IIgsSampleHeader { - uint16 type; - uint8 pitch; ///< Logarithmic, base is 2**(1/12), unknown multiplier (Possibly in range 1040-1080) - uint8 unknownByte_Ofs3; // 0x7F in Gold Rush's sound resource 60, 0 in all others. - uint8 volume; ///< Current guess: Logarithmic in 6 dB steps - uint8 unknownByte_Ofs5; ///< 0 in all tested samples. - uint16 instrumentSize; ///< Little endian. 44 in all tested samples. A guess. - uint16 sampleSize; ///< Little endian. Accurate in all tested samples excluding Manhunter I's sound resource 16. - IIgsInstrumentHeader instrument; - - /** - * Read an Apple IIGS AGI sample header from the given stream. - * @param stream The source stream from which to read the data. - * @return True if successful, false otherwise. - */ - bool read(Common::SeekableReadStream &stream); - bool finalize(Common::SeekableReadStream &uint8Wave); -}; +#define SOUND_EMU_MIDI 7 /** * AGI sound note structure. @@ -200,87 +58,38 @@ struct AgiNote { } }; -struct IIgsChannelInfo { - const IIgsInstrumentHeader *ins; ///< Instrument info - const int8 *relocatedSample; ///< Source sample data (8-bit signed format) using relocation - const int8 *unrelocatedSample; ///< Source sample data (8-bit signed format) without relocation - frac_t pos; ///< Current sample position - frac_t posAdd; ///< Current sample position adder (Calculated using note, vibrato etc) - uint8 origNote; ///< The original note without the added relative pitch - frac_t note; ///< Note (With the added relative pitch) - frac_t vol; ///< Current volume (Takes both channel volume and enveloping into account) - frac_t chanVol; ///< Channel volume - frac_t startEnvVol; ///< Starting envelope volume - frac_t envVol; ///< Current envelope volume - uint envSeg; ///< Current envelope segment - uint size; ///< Sample size - bool loop; ///< Should we loop the sample? - bool end; ///< Has the playing ended? - - void rewind(); ///< Rewinds the sound playing on this channel to its start - void setChannelVolume(uint8 volume); ///< Sets the channel volume - void setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample); ///< Sets the instrument to be used on this channel - void noteOn(uint8 noteParam, uint8 velocity); ///< Starts playing a note on this channel - void noteOff(uint8 velocity); ///< Releases the note on this channel - void stop(); ///< Stops the note playing on this channel instantly - bool playing(); ///< Is there a note playing on this channel? -}; - -struct CoCoNote { - uint8 freq; - uint8 volume; - uint16 duration; ///< Note duration - - /** Reads a CoCoNote through the given pointer. */ - void read(const uint8 *ptr) { - freq = *ptr; - volume = *(ptr + 1); - duration = READ_LE_UINT16(ptr + 2); - } -}; - /** * AGI sound resource types. * It's probably coincidence that all the values here are powers of two * as they're simply the different used values in AGI sound resources' * starts (The first 16-bit little endian word, to be precise). */ -enum AgiSoundType { +enum AgiSoundEmuType { AGI_SOUND_SAMPLE = 0x0001, AGI_SOUND_MIDI = 0x0002, AGI_SOUND_4CHN = 0x0008 }; -enum AgiSoundFlags { - AGI_SOUND_LOOP = 0x0001, - AGI_SOUND_ENVELOPE = 0x0002 -}; -enum AgiSoundEnv { - AGI_SOUND_ENV_ATTACK = 3, - AGI_SOUND_ENV_DECAY = 2, - AGI_SOUND_ENV_SUSTAIN = 1, - AGI_SOUND_ENV_RELEASE = 0 -}; +class SoundMgr; -/** - * AGI engine sound channel structure. - */ -struct ChannelInfo { - AgiSoundType type; - const uint8 *ptr; // Pointer to the AgiNote data - const int16 *ins; - int32 size; - uint32 phase; - uint32 flags; // ORs values from AgiSoundFlags - AgiSoundEnv adsr; - int32 timer; - uint32 end; - uint32 freq; - uint32 vol; - uint32 env; -}; +class SoundGen { +public: + SoundGen(AgiEngine *vm, Audio::Mixer *pMixer) : _vm(vm), _mixer(pMixer) { + _sampleRate = pMixer->getOutputRate(); + } -class SoundMgr; + virtual ~SoundGen() {} + + virtual void play(int resnum) = 0; + virtual void stop(void) = 0; + + AgiEngine *_vm; + + Audio::Mixer *_mixer; + Audio::SoundHandle _soundHandle; + + uint32 _sampleRate; +}; /** * AGI sound resource structure. @@ -302,7 +111,7 @@ public: * from memory using free() or delegate the responsibility onwards to some other * function! */ - static AgiSound *createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager); + static AgiSound *createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager, int soundemu); protected: SoundMgr &_manager; ///< AGI sound manager object @@ -313,7 +122,7 @@ protected: class PCjrSound : public AgiSound { public: PCjrSound(uint8 *data, uint32 len, int resnum, SoundMgr &manager); - ~PCjrSound() { if (_data != NULL) free(_data); } + ~PCjrSound() { free(_data); } virtual uint16 type() { return _type; } const uint8 *getVoicePointer(uint voiceNum); protected: @@ -322,192 +131,30 @@ protected: uint16 _type; ///< Sound resource type }; -class IIgsMidi : public AgiSound { -public: - IIgsMidi(uint8 *data, uint32 len, int resnum, SoundMgr &manager); - ~IIgsMidi() { if (_data != NULL) free(_data); } - virtual uint16 type() { return _type; } - virtual const uint8 *getPtr() { return _ptr; } - virtual void setPtr(const uint8 *ptr) { _ptr = ptr; } - virtual void rewind() { _ptr = _data + 2; _midiTicks = _soundBufTicks = 0; } -protected: - uint8 *_data; ///< Raw sound resource data - const uint8 *_ptr; ///< Pointer to the current position in the MIDI data - uint32 _len; ///< Length of the raw sound resource - uint16 _type; ///< Sound resource type -public: - uint _midiTicks; ///< MIDI song position in ticks (1/60ths of a second) - uint _soundBufTicks; ///< Sound buffer position in ticks (1/60ths of a second) -}; - -class IIgsSample : public AgiSound { -public: - IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager); - ~IIgsSample() { delete[] _sample; } - virtual uint16 type() { return _header.type; } - const IIgsSampleHeader &getHeader() const { return _header; } - const int8 *getSample() const { return _sample; } -protected: - IIgsSampleHeader _header; ///< Apple IIGS AGI sample header - int8 *_sample; ///< Sample data (8-bit signed format) -}; - -/** Apple IIGS MIDI program change to instrument number mapping. */ -struct MidiProgramChangeMapping { - byte midiProgToInst[44]; ///< Lookup table for the MIDI program number to instrument number mapping - byte undefinedInst; ///< The undefined instrument number - - // Maps the MIDI program number to an instrument number - byte map(uint midiProg) const { - return midiProg < ARRAYSIZE(midiProgToInst) ? midiProgToInst[midiProg] : undefinedInst; - } -}; - -/** Apple IIGS AGI instrument set information. */ -struct InstrumentSetInfo { - uint byteCount; ///< Length of the whole instrument set in bytes - uint instCount; ///< Amount of instrument in the set - const char *md5; ///< MD5 hex digest of the whole instrument set - const char *waveFileMd5; ///< MD5 hex digest of the wave file (i.e. the sample data used by the instruments) - const MidiProgramChangeMapping &progToInst; ///< Program change to instrument number mapping -}; - -/** Apple IIGS AGI executable file information. */ -struct IIgsExeInfo { - enum AgiGameID gameid; ///< Game ID - const char *exePrefix; ///< Prefix of the Apple IIGS AGI executable (e.g. "SQ", "PQ", "KQ4" etc) - uint agiVer; ///< Apple IIGS AGI version number, not strictly needed - uint exeSize; ///< Size of the Apple IIGS AGI executable file in bytes - uint instSetStart; ///< Starting offset of the instrument set inside the executable file - const InstrumentSetInfo &instSet; ///< Information about the used instrument set -}; - -class IIgsMidiChannel { -public: - IIgsMidiChannel() : _instrument(0), _sample(0), _volume(0) {} - uint activeSounds() const; ///< How many active sounds are playing? - void setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample); - void setVolume(uint8 volume); - void noteOff(uint8 note, uint8 velocity); - void noteOn(uint8 note, uint8 velocity); - void stopSounds(); ///< Clears the channel of any sounds - void removeStoppedSounds(); ///< Removes all stopped sounds from this MIDI channel -public: - typedef Common::Array<IIgsChannelInfo>::const_iterator const_iterator; - typedef Common::Array<IIgsChannelInfo>::iterator iterator; - Common::Array<IIgsChannelInfo> _gsChannels; ///< Apple IIGS channels playing on this MIDI channel -protected: - const IIgsInstrumentHeader *_instrument; ///< Instrument used on this MIDI channel - const int8 *_sample; ///< Sample data used on this MIDI channel - uint8 _volume; ///< MIDI controller number 7 (Volume) -}; - -/** - * Class for managing Apple IIGS sound channels. - * TODO: Check what instruments are used by default on the MIDI channels - * FIXME: Some instrument choices sound wrong - */ -class IIgsSoundMgr { -public: - typedef Common::Array<IIgsMidiChannel>::const_iterator const_iterator; - typedef Common::Array<IIgsMidiChannel>::iterator iterator; - static const uint kSfxMidiChannel = 0; ///< The MIDI channel used for playing sound effects -public: - // For initializing - IIgsSoundMgr(); - void setProgramChangeMapping(const MidiProgramChangeMapping *mapping); - bool loadInstrumentHeaders(const Common::FSNode &exePath, const IIgsExeInfo &exeInfo); - bool loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo &exeInfo); - // Miscellaneous methods - uint activeSounds() const; ///< How many active sounds are playing? - void stopSounds(); ///< Stops all sounds - void removeStoppedSounds(); ///< Removes all stopped sounds from the MIDI channels - // For playing Apple IIGS AGI samples (Sound effects etc) - bool playSampleSound(const IIgsSampleHeader &sampleHeader, const int8 *sample); - // MIDI commands - void midiNoteOff(uint8 channel, uint8 note, uint8 velocity); - void midiNoteOn(uint8 channel, uint8 note, uint8 velocity); - void midiController(uint8 channel, uint8 controller, uint8 value); - void midiProgramChange(uint8 channel, uint8 program); - void midiPitchWheel(uint8 wheelPos); -protected: - const IIgsInstrumentHeader* getInstrument(uint8 program) const; -public: - Common::Array<IIgsMidiChannel> _midiChannels; ///< Information about each MIDI channel -protected: - Common::Array<int8> _wave; ///< Sample data used by the Apple IIGS MIDI instruments - const MidiProgramChangeMapping *_midiProgToInst; ///< MIDI program change to instrument number mapping - Common::Array<IIgsInstrumentHeader> _instruments; ///< Instruments used by the Apple IIGS AGI -}; - -class AgiEngine; -class AgiBase; - -class SoundMgr : public Audio::AudioStream { - AgiBase *_vm; +class SoundMgr { public: - SoundMgr(AgiBase *agi, Audio::Mixer *pMixer); + SoundMgr(AgiEngine *agi, Audio::Mixer *pMixer); ~SoundMgr(); - virtual void setVolume(uint8 volume); - - // AudioStream API - int readBuffer(int16 *buffer, const int numSamples) { - premixerCall(buffer, numSamples / 2); - return numSamples; - } - - bool isStereo() const { - return false; - } - bool endOfData() const { - return false; - } - - int getRate() const { - // FIXME: Ideally, we should use _sampleRate. - return 22050; - } - -private: - Audio::Mixer *_mixer; - Audio::SoundHandle _soundHandle; - uint32 _sampleRate; - - bool _playing; - ChannelInfo _chn[NUM_CHANNELS]; - IIgsSoundMgr _gsSound; - int _endflag; - int _playingSound; - uint8 _env; - bool _disabledMidi; - - int16 *_sndBuffer; - const int16 *_waveform; - - bool _useChorus; - - void premixerCall(int16 *buf, uint len); - void fillAudio(void *udata, int16 *stream, uint len); + void setVolume(uint8 volume); -public: void unloadSound(int); void playSound(); int initSound(); void deinitSound(); void startSound(int, int); void stopSound(); - void stopNote(int i); - void playNote(int i, int freq, int vol); - void playAgiSound(); - void playCoCoSound(); - uint32 mixSound(); - bool loadInstruments(); - void playMidiSound(); - void playSampleSound(); - const IIgsExeInfo *getIIgsExeInfo(enum AgiGameID gameid) const; - static bool convertWave(Common::SeekableReadStream &source, int8 *dest, uint length); + + void soundIsFinished(); + +private: + int _endflag; + AgiEngine *_vm; + + SoundGen *_soundGen; + + int _playingSound; }; } // End of namespace Agi diff --git a/engines/agi/sound_2gs.cpp b/engines/agi/sound_2gs.cpp new file mode 100644 index 0000000000..cc1cd0f6d5 --- /dev/null +++ b/engines/agi/sound_2gs.cpp @@ -0,0 +1,919 @@ +/* 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/config-manager.h" +#include "common/fs.h" +#include "common/md5.h" +#include "common/str-array.h" + +#include "agi/agi.h" +#include "agi/sound_2gs.h" + +namespace Agi { + +SoundGen2GS::SoundGen2GS(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer) { + _disabledMidi = !loadInstruments(); + + _playingSound = -1; + _playing = false; + + _sndBuffer = (int16 *)calloc(2, BUFFER_SIZE); + + _midiChannels.resize(16); // Set the amount of available MIDI channels + + _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); +} + +SoundGen2GS::~SoundGen2GS() { + _mixer->stopHandle(_soundHandle); + + free(_sndBuffer); +} + +int SoundGen2GS::readBuffer(int16 *buffer, const int numSamples) { + fillAudio(buffer, numSamples / 2); + + return numSamples; +} + +void SoundGen2GS::play(int resnum) { + AgiSoundEmuType type; + + _playingSound = resnum; + + type = (AgiSoundEmuType)_vm->_game.sounds[resnum]->type(); + + assert (type == AGI_SOUND_SAMPLE || type == AGI_SOUND_MIDI); + + switch (type) { + case AGI_SOUND_SAMPLE: { + IIgsSample *sampleRes = (IIgsSample *) _vm->_game.sounds[_playingSound]; + playSampleSound(sampleRes->getHeader(), sampleRes->getSample()); + break; + } + case AGI_SOUND_MIDI: + ((IIgsMidi *) _vm->_game.sounds[_playingSound])->rewind(); + break; + default: + break; + } +} + +void SoundGen2GS::stop() { + _playingSound = -1; + + // Stops all sounds on all MIDI channels + for (iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter) + iter->stopSounds(); +} + +void SoundGen2GS::playSound() { + if (_playingSound == -1) + return; + + if (_vm->_game.sounds[_playingSound]->type() == AGI_SOUND_MIDI) { + playMidiSound(); + //warning("playSound: Trying to play an Apple IIGS MIDI sound. Not yet implemented"); + } else if (_vm->_game.sounds[_playingSound]->type() == AGI_SOUND_SAMPLE) { + //debugC(3, kDebugLevelSound, "playSound: Trying to play an Apple IIGS sample"); + playSampleSound(); + } + + if (!_playing) { + _vm->_sound->soundIsFinished(); + + _playingSound = -1; + } +} + +uint32 SoundGen2GS::mixSound() { + int i, b; + + memset(_sndBuffer, 0, BUFFER_SIZE << 1); + + if (!_playing || _playingSound == -1) + return BUFFER_SIZE; + + // Handle Apple IIGS sound mixing here + // TODO: Implement playing both waves in an oscillator + // TODO: Implement swap-mode in an oscillator + for (uint midiChan = 0; midiChan < _midiChannels.size(); midiChan++) { + for (uint gsChan = 0; gsChan < _midiChannels[midiChan]._gsChannels.size(); gsChan++) { + IIgsChannelInfo &channel = _midiChannels[midiChan]._gsChannels[gsChan]; + if (channel.playing()) { // Only mix in actively playing channels + // Frequency multiplier was 1076.0 based on tests made with MESS 0.117. + // Tests made with KEGS32 averaged the multiplier to around 1045. + // So this is a guess but maybe it's 1046.5... i.e. C6's frequency? + double hertz = C6_FREQ * pow(SEMITONE, fracToDouble(channel.note)); + channel.posAdd = doubleToFrac(hertz / getRate()); + channel.vol = doubleToFrac(fracToDouble(channel.envVol) * fracToDouble(channel.chanVol) / 127.0); + double tempVol = fracToDouble(channel.vol)/127.0; + for (i = 0; i < IIGS_BUFFER_SIZE; i++) { + b = channel.relocatedSample[fracToInt(channel.pos)]; + // TODO: Find out what volume/amplification setting is loud enough + // but still doesn't clip when playing many channels on it. + _sndBuffer[i] += (int16) (b * tempVol * 256/4); + channel.pos += channel.posAdd; + + if (channel.pos >= intToFrac(channel.size)) { + if (channel.loop) { + // Don't divide by zero on zero length samples + channel.pos %= intToFrac(channel.size + (channel.size == 0)); + // Probably we should loop the envelope too + channel.envSeg = 0; + channel.envVol = channel.startEnvVol; + } else { + channel.pos = channel.chanVol = 0; + channel.end = true; + break; + } + } + } + + if (channel.envSeg < ENVELOPE_SEGMENT_COUNT) { + const IIgsEnvelopeSegment &seg = channel.ins->env.seg[channel.envSeg]; + // I currently assume enveloping works with the same speed as the MIDI + // (i.e. with 1/60ths of a second ticks). + // TODO: Check if enveloping really works with the same speed as MIDI + frac_t envVolDelta = doubleToFrac(seg.inc/256.0); + if (intToFrac(seg.bp) >= channel.envVol) { + channel.envVol += envVolDelta; + if (channel.envVol >= intToFrac(seg.bp)) { + channel.envVol = intToFrac(seg.bp); + channel.envSeg += 1; + } + } else { + channel.envVol -= envVolDelta; + if (channel.envVol <= intToFrac(seg.bp)) { + channel.envVol = intToFrac(seg.bp); + channel.envSeg += 1; + } + } + } + } + } + } + + removeStoppedSounds(); + + return IIGS_BUFFER_SIZE; +} + +void SoundGen2GS::fillAudio(int16 *stream, uint len) { + uint32 p = 0; + + // current number of audio bytes in _sndBuffer + static uint32 data_available = 0; + // offset of start of audio bytes in _sndBuffer + static uint32 data_offset = 0; + + len <<= 2; + + debugC(5, kDebugLevelSound, "(%p, %d)", (void *)stream, len); + + while (len > data_available) { + memcpy((uint8 *)stream + p, (uint8*)_sndBuffer + data_offset, data_available); + p += data_available; + len -= data_available; + + playSound(); + data_available = mixSound() << 1; + data_offset = 0; + } + + memcpy((uint8 *)stream + p, (uint8*)_sndBuffer + data_offset, len); + data_offset += len; + data_available -= len; +} + +void SoundGen2GS::playSampleSound() { + if (_vm->_soundemu != SOUND_EMU_APPLE2GS) { + warning("Trying to play a sample but not using Apple IIGS sound emulation mode"); + return; + } + + if (_playingSound != -1) + _playing = activeSounds() > 0; +} + +void SoundGen2GS::stopSounds() { + // Stops all sounds on all MIDI channels + for (iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter) + iter->stopSounds(); +} + +bool SoundGen2GS::playSampleSound(const IIgsSampleHeader &sampleHeader, const int8 *sample) { + stopSounds(); + IIgsMidiChannel &channel = _midiChannels[kSfxMidiChannel]; + + channel.setInstrument(&sampleHeader.instrument, sample); + channel.setVolume(sampleHeader.volume); + channel.noteOn(sampleHeader.pitch, 64); // Use default velocity (i.e. 64) + + return true; +} + +void SoundGen2GS::playMidiSound() { + if (_disabledMidi) + return; + + const uint8 *p; + uint8 parm1, parm2; + static uint8 cmd, ch; + + if (_playingSound == -1 || _vm->_game.sounds[_playingSound] == NULL) { + warning("Error playing Apple IIGS MIDI sound resource"); + _playing = false; + + return; + } + + IIgsMidi *midiObj = (IIgsMidi *) _vm->_game.sounds[_playingSound]; + + _playing = true; + p = midiObj->getPtr(); + + midiObj->_soundBufTicks++; + + while (true) { + uint8 readByte = *p; + + // Check for end of MIDI sequence marker (Can also be here before delta-time) + if (readByte == MIDI_BYTE_STOP_SEQUENCE) { + debugC(3, kDebugLevelSound, "End of MIDI sequence (Before reading delta-time)"); + _playing = false; + + midiObj->rewind(); + + return; + } else if (readByte == MIDI_BYTE_TIMER_SYNC) { + debugC(3, kDebugLevelSound, "Timer sync"); + p++; // Jump over the timer sync byte as it's not needed + + continue; + } + + uint8 deltaTime = readByte; + if (midiObj->_midiTicks + deltaTime > midiObj->_soundBufTicks) { + break; + } + midiObj->_midiTicks += deltaTime; + p++; // Jump over the delta-time byte as it was already taken care of + + // Check for end of MIDI sequence marker (This time it after reading delta-time) + if (*p == MIDI_BYTE_STOP_SEQUENCE) { + debugC(3, kDebugLevelSound, "End of MIDI sequence (After reading delta-time)"); + _playing = false; + + midiObj->rewind(); + + return; + } + + // Separate byte into command and channel if it's a command byte. + // Otherwise use running status (i.e. previously set command and channel). + if (*p & 0x80) { + cmd = *p++; + ch = cmd & 0x0f; + cmd >>= 4; + } + + switch (cmd) { + case MIDI_CMD_NOTE_OFF: + parm1 = *p++; + parm2 = *p++; + midiNoteOff(ch, parm1, parm2); + break; + case MIDI_CMD_NOTE_ON: + parm1 = *p++; + parm2 = *p++; + midiNoteOn(ch, parm1, parm2); + break; + case MIDI_CMD_CONTROLLER: + parm1 = *p++; + parm2 = *p++; + midiController(ch, parm1, parm2); + break; + case MIDI_CMD_PROGRAM_CHANGE: + parm1 = *p++; + midiProgramChange(ch, parm1); + break; + case MIDI_CMD_PITCH_WHEEL: + parm1 = *p++; + parm2 = *p++; + + uint16 wheelPos = ((parm2 & 0x7F) << 7) | (parm1 & 0x7F); // 14-bit value + midiPitchWheel(wheelPos); + break; + } + } + + midiObj->setPtr(p); +} + +void SoundGen2GS::midiNoteOff(uint8 channel, uint8 note, uint8 velocity) { + _midiChannels[channel].noteOff(note, velocity); + debugC(3, kDebugLevelSound, "note off, channel %02x, note %02x, velocity %02x", channel, note, velocity); +} + +void SoundGen2GS::midiNoteOn(uint8 channel, uint8 note, uint8 velocity) { + _midiChannels[channel].noteOn(note, velocity); + debugC(3, kDebugLevelSound, "note on, channel %02x, note %02x, velocity %02x", channel, note, velocity); +} + +// TODO: Check if controllers behave differently on different MIDI channels +// TODO: Doublecheck what other controllers than the volume controller do +void SoundGen2GS::midiController(uint8 channel, uint8 controller, uint8 value) { + IIgsMidiChannel &midiChannel = _midiChannels[channel]; + + // The tested Apple IIGS AGI MIDI resources only used + // controllers 0 (Bank select?), 7 (Volume) and 64 (Sustain On/Off). + // Controller 0's parameter was in range 94-127, + // controller 7's parameter was in range 0-127 and + // controller 64's parameter was always 0 (i.e. sustain off). + bool unimplemented = false; + switch (controller) { + case 7: // Volume + midiChannel.setVolume(value); + break; + default: + unimplemented = true; + break; + } + debugC(3, kDebugLevelSound, "controller %02x, ch %02x, val %02x%s", controller, channel, value, unimplemented ? " (Unimplemented)" : ""); +} + +void SoundGen2GS::midiProgramChange(uint8 channel, uint8 program) { + _midiChannels[channel].setInstrument(getInstrument(program), _wave.begin()); + debugC(3, kDebugLevelSound, "program change %02x, channel %02x", program, channel); +} + +void SoundGen2GS::midiPitchWheel(uint8 wheelPos) { + // In all the tested Apple IIGS AGI MIDI resources + // pitch wheel commands always used 0x2000 (Center position). + // Therefore it should be quite safe to ignore this command. + debugC(3, kDebugLevelSound, "pitch wheel position %04x (Unimplemented)", wheelPos); +} + +const IIgsInstrumentHeader* SoundGen2GS::getInstrument(uint8 program) const { + return &_instruments[_midiProgToInst->map(program)]; +} + +void SoundGen2GS::setProgramChangeMapping(const MidiProgramChangeMapping *mapping) { + _midiProgToInst = mapping; +} + +void SoundGen2GS::removeStoppedSounds() { + for (Common::Array<IIgsMidiChannel>::iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter) + iter->removeStoppedSounds(); +} + +uint SoundGen2GS::activeSounds() const { + uint result = 0; + + for (Common::Array<IIgsMidiChannel>::const_iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter) + result += iter->activeSounds(); + + return result; +} + +IIgsMidi::IIgsMidi(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) { + _data = data; // Save the resource pointer + _ptr = _data + 2; // Set current position to just after the header + _len = len; // Save the resource's length + _type = READ_LE_UINT16(data); // Read sound resource's type + _midiTicks = _soundBufTicks = 0; + _isValid = (_type == AGI_SOUND_MIDI) && (_data != NULL) && (_len >= 2); + + if (!_isValid) // Check for errors + warning("Error creating Apple IIGS midi sound from resource %d (Type %d, length %d)", resnum, _type, len); +} + +/** + * Convert sample from 8-bit unsigned to 8-bit signed format. + * @param source Source stream containing the 8-bit unsigned sample data. + * @param dest Destination buffer for the 8-bit signed sample data. + * @param length Length of the sample data to be converted. + */ +static bool convertWave(Common::SeekableReadStream &source, int8 *dest, uint length) { + // Convert the wave from 8-bit unsigned to 8-bit signed format + for (uint i = 0; i < length; i++) + dest[i] = (int8) ((int) source.readByte() - 128); + return !(source.eos() || source.err()); +} + +IIgsSample::IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) { + Common::MemoryReadStream stream(data, len, DisposeAfterUse::YES); + + // Check that the header was read ok and that it's of the correct type + if (_header.read(stream) && _header.type == AGI_SOUND_SAMPLE) { // An Apple IIGS AGI sample resource + uint32 sampleStartPos = stream.pos(); + uint32 tailLen = stream.size() - sampleStartPos; + + if (tailLen < _header.sampleSize) { // Check if there's no room for the sample data in the stream + // Apple IIGS Manhunter I: Sound resource 16 has only 16074 bytes + // of sample data although header says it should have 16384 bytes. + warning("Apple IIGS sample (%d) too short (%d bytes. Should be %d bytes). Using the part that's left", + resnum, tailLen, _header.sampleSize); + + _header.sampleSize = (uint16) tailLen; // Use the part that's left + } + + if (_header.pitch > 0x7F) { // Check if the pitch is invalid + warning("Apple IIGS sample (%d) has too high pitch (0x%02x)", resnum, _header.pitch); + + _header.pitch &= 0x7F; // Apple IIGS AGI probably did it this way too + } + + // Finalize the header info using the 8-bit unsigned sample data + _header.finalize(stream); + + // Convert sample data from 8-bit unsigned to 8-bit signed format + stream.seek(sampleStartPos); + _sample = new int8[_header.sampleSize]; + + if (_sample != NULL) + _isValid = convertWave(stream, _sample, _header.sampleSize); + } + + if (!_isValid) // Check for errors + warning("Error creating Apple IIGS sample from resource %d (Type %d, length %d)", resnum, _header.type, len); +} + +/** Reads an Apple IIGS envelope from then given stream. */ +bool IIgsEnvelope::read(Common::SeekableReadStream &stream) { + for (int segNum = 0; segNum < ENVELOPE_SEGMENT_COUNT; segNum++) { + seg[segNum].bp = stream.readByte(); + seg[segNum].inc = stream.readUint16LE(); + } + + return !(stream.eos() || stream.err()); +} + +/** Reads an Apple IIGS wave information structure from the given stream. */ +bool IIgsWaveInfo::read(Common::SeekableReadStream &stream, bool ignoreAddr) { + top = stream.readByte(); + addr = stream.readByte() * 256; + size = (1 << (stream.readByte() & 7)) * 256; + + // Read packed mode byte and parse it into parts + byte packedModeByte = stream.readByte(); + channel = (packedModeByte >> 4) & 1; // Bit 4 + mode = (packedModeByte >> 1) & 3; // Bits 1-2 + halt = (packedModeByte & 1) != 0; // Bit 0 (Converted to boolean) + + relPitch = stream.readSint16LE(); + + // Zero the wave address if we want to ignore the wave address info + if (ignoreAddr) + addr = 0; + + return !(stream.eos() || stream.err()); +} + +bool IIgsWaveInfo::finalize(Common::SeekableReadStream &uint8Wave) { + uint32 startPos = uint8Wave.pos(); // Save stream's starting position + uint8Wave.seek(addr, SEEK_CUR); // Seek to wave's address + + // Calculate the true sample size (A zero ends the sample prematurely) + uint trueSize = size; // Set a default value for the result + for (uint i = 0; i < size; i++) { + if (uint8Wave.readByte() == 0) { + trueSize = i; + // A zero in the sample stream turns off looping + // (At least that's what MESS 0.117 and KEGS32 0.91 seem to do) + if (mode == OSC_MODE_LOOP) + mode = OSC_MODE_ONESHOT; + break; + } + } + size = trueSize; // Set the true sample size + + uint8Wave.seek(startPos); // Seek back to the stream's starting position + + return true; +} + +bool IIgsOscillator::finalize(Common::SeekableReadStream &uint8Wave) { + for (uint i = 0; i < WAVES_PER_OSCILLATOR; i++) + if (!waves[i].finalize(uint8Wave)) + return false; + + return true; +} + +bool IIgsOscillatorList::read(Common::SeekableReadStream &stream, uint oscillatorCount, bool ignoreAddr) { + // First read the A waves and then the B waves for the oscillators + for (uint waveNum = 0; waveNum < WAVES_PER_OSCILLATOR; waveNum++) + for (uint oscNum = 0; oscNum < oscillatorCount; oscNum++) + if (!osc[oscNum].waves[waveNum].read(stream, ignoreAddr)) + return false; + + count = oscillatorCount; // Set the oscillator count + + return true; +} + +bool IIgsOscillatorList::finalize(Common::SeekableReadStream &uint8Wave) { + for (uint i = 0; i < count; i++) + if (!osc[i].finalize(uint8Wave)) + return false; + + return true; +} + +bool IIgsInstrumentHeader::read(Common::SeekableReadStream &stream, bool ignoreAddr) { + env.read(stream); + relseg = stream.readByte(); + /*byte priority =*/ stream.readByte(); // Not needed? 32 in all tested data. + bendrange = stream.readByte(); + vibdepth = stream.readByte(); + vibspeed = stream.readByte(); + /*byte spare =*/ stream.readByte(); // Not needed? 0 in all tested data. + byte wac = stream.readByte(); // Read A wave count + byte wbc = stream.readByte(); // Read B wave count + oscList.read(stream, wac, ignoreAddr); // Read the oscillators + return (wac == wbc) && !(stream.eos() || stream.err()); // A and B wave counts must match +} + +bool IIgsInstrumentHeader::finalize(Common::SeekableReadStream &uint8Wave) { + return oscList.finalize(uint8Wave); +} + +bool IIgsSampleHeader::read(Common::SeekableReadStream &stream) { + type = stream.readUint16LE(); + pitch = stream.readByte(); + unknownByte_Ofs3 = stream.readByte(); + volume = stream.readByte(); + unknownByte_Ofs5 = stream.readByte(); + instrumentSize = stream.readUint16LE(); + sampleSize = stream.readUint16LE(); + // Read the instrument header *ignoring* its wave address info + + return instrument.read(stream, true); +} + +bool IIgsSampleHeader::finalize(Common::SeekableReadStream &uint8Wave) { + return instrument.finalize(uint8Wave); +} + +void IIgsMidiChannel::stopSounds() { + // Stops all sounds on this single MIDI channel + for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) + iter->stop(); + + _gsChannels.clear(); +} + +void IIgsMidiChannel::removeStoppedSounds() { + for (int i = _gsChannels.size() - 1; i >= 0; i--) + if (!_gsChannels[i].playing()) + _gsChannels.remove_at(i); +} + +uint IIgsMidiChannel::activeSounds() const { + uint result = 0; + + for (const_iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) + if (!iter->end) + result++; + + return result; +} + +void IIgsMidiChannel::setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample) { + _instrument = instrument; + _sample = sample; + + // Set program on each Apple IIGS channel playing on this MIDI channel + for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) + iter->setInstrument(instrument, sample); +} + +void IIgsMidiChannel::setVolume(uint8 volume) { + _volume = volume; + + // Set volume on each Apple IIGS channel playing on this MIDI channel + for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) + iter->setChannelVolume(volume); +} + +void IIgsMidiChannel::noteOff(uint8 note, uint8 velocity) { + // Go through all the notes playing on this MIDI channel + // and turn off the ones that are playing the given note + for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) + if (iter->origNote == note) + iter->noteOff(velocity); +} + +void IIgsMidiChannel::noteOn(uint8 note, uint8 velocity) { + IIgsChannelInfo channel; + + // Use the default channel volume and instrument + channel.setChannelVolume(_volume); + channel.setInstrument(_instrument, _sample); + + // Set the note on and save the channel + channel.noteOn(note, velocity); + _gsChannels.push_back(channel); +} + +void IIgsChannelInfo::rewind() { + this->envVol = this->startEnvVol; + this->envSeg = 0; + this->pos = intToFrac(0); +} + +void IIgsChannelInfo::setChannelVolume(uint8 volume) { + this->chanVol = intToFrac(volume); +} + +void IIgsChannelInfo::setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample) { + assert(instrument != NULL && sample != NULL); + this->ins = instrument; + this->unrelocatedSample = sample; +} + +// TODO/FIXME: Implement correctly and fully (Take velocity into account etc) +void IIgsChannelInfo::noteOn(uint8 noteParam, uint8 velocity) { + this->origNote = noteParam; + this->startEnvVol = intToFrac(0); + rewind(); + + const IIgsWaveInfo *waveInfo = NULL; + + for (uint i = 0; i < ins->oscList.count; i++) + if (ins->oscList(i).waves[0].top >= noteParam) + waveInfo = &ins->oscList(i).waves[0]; + + assert(waveInfo != NULL); + + this->relocatedSample = this->unrelocatedSample + waveInfo->addr; + this->posAdd = intToFrac(0); + this->note = intToFrac(noteParam) + doubleToFrac(waveInfo->relPitch/256.0); + this->vol = doubleToFrac(fracToDouble(this->envVol) * fracToDouble(this->chanVol) / 127.0); + this->loop = (waveInfo->mode == OSC_MODE_LOOP); + this->size = waveInfo->size - waveInfo->addr; + this->end = waveInfo->halt; +} + +// TODO/FIXME: Implement correctly and fully (Take release time and velocity into account etc) +void IIgsChannelInfo::noteOff(uint8 velocity) { + this->loop = false; + this->envSeg = ins->relseg; +} + +void IIgsChannelInfo::stop() { + this->end = true; +} + +bool IIgsChannelInfo::playing() { + return !this->end; +} + +/** + * A function object (i.e. a functor) for testing if a Common::FSNode + * object's name is equal (Ignoring case) to a string or to at least + * one of the strings in a list of strings. Can be used e.g. with find_if(). + */ +struct fsnodeNameEqualsIgnoreCase : public Common::UnaryFunction<const Common::FSNode&, bool> { +// FIXME: This should be replaced; use SearchMan instead + fsnodeNameEqualsIgnoreCase(const Common::StringArray &str) : _str(str) {} + fsnodeNameEqualsIgnoreCase(const Common::String str) { _str.push_back(str); } + bool operator()(const Common::FSNode ¶m) const { + for (Common::StringArray::const_iterator iter = _str.begin(); iter != _str.end(); ++iter) + if (param.getName().equalsIgnoreCase(*iter)) + return true; + return false; + } +private: + Common::StringArray _str; +}; + +bool SoundGen2GS::loadInstruments() { + // Check that the platform is Apple IIGS, as only it uses custom instruments + if (_vm->getPlatform() != Common::kPlatformApple2GS) { + debugC(3, kDebugLevelSound, "Platform isn't Apple IIGS so not loading any instruments"); + return true; + } + + // Get info on the particular Apple IIGS AGI game's executable + const IIgsExeInfo *exeInfo = getIIgsExeInfo((enum AgiGameID) _vm->getGameID()); + if (exeInfo == NULL) { + warning("Unsupported Apple IIGS game, not loading instruments"); + return false; + } + + // List files in the game path + Common::FSList fslist; + Common::FSNode dir(ConfMan.get("path")); + if (!dir.getChildren(fslist, Common::FSNode::kListFilesOnly)) { + warning("Invalid game path (\"%s\"), not loading Apple IIGS instruments", dir.getPath().c_str()); + return false; + } + + // Populate executable filenames list (Long filename and short filename) for searching + Common::StringArray exeNames; + exeNames.push_back(Common::String(exeInfo->exePrefix) + ".SYS16"); + exeNames.push_back(Common::String(exeInfo->exePrefix) + ".SYS"); + + // Populate wave filenames list (Long filename and short filename) for searching + Common::StringArray waveNames; + waveNames.push_back("SIERRASTANDARD"); + waveNames.push_back("SIERRAST"); + + // Search for the executable file and the wave file (i.e. check if any of the filenames match) + Common::FSList::const_iterator exeFsnode, waveFsnode; + exeFsnode = Common::find_if(fslist.begin(), fslist.end(), fsnodeNameEqualsIgnoreCase(exeNames)); + waveFsnode = Common::find_if(fslist.begin(), fslist.end(), fsnodeNameEqualsIgnoreCase(waveNames)); + + // Make sure that we found the executable file + if (exeFsnode == fslist.end()) { + warning("Couldn't find Apple IIGS game executable (%s), not loading instruments", exeNames.begin()->c_str()); + return false; + } + + // Make sure that we found the wave file + if (waveFsnode == fslist.end()) { + warning("Couldn't find Apple IIGS wave file (%s), not loading instruments", waveNames.begin()->c_str()); + return false; + } + + // Set the MIDI program change to instrument number mapping and + // load the instrument headers and their sample data. + // None of the tested SIERRASTANDARD-files have zeroes in them so + // there's no need to check for prematurely ending samples here. + setProgramChangeMapping(&exeInfo->instSet.progToInst); + return loadWaveFile(*waveFsnode, *exeInfo) && loadInstrumentHeaders(*exeFsnode, *exeInfo); +} + +/** Older Apple IIGS AGI MIDI program change to instrument number mapping. */ +static const MidiProgramChangeMapping progToInstMappingV1 = { + {19, 20, 22, 23, 21, 24, 5, 5, 5, 5, + 6, 7, 10, 9, 11, 9, 15, 8, 5, 5, + 17, 16, 18, 12, 14, 5, 5, 5, 5, 5, + 0, 1, 2, 9, 3, 4, 15, 2, 2, 2, + 25, 13, 13, 25}, + 5 +}; + +/** Newer Apple IIGS AGI MIDI program change to instrument number mapping. */ +static const MidiProgramChangeMapping progToInstMappingV2 = { + {21, 22, 24, 25, 23, 26, 6, 6, 6, 6, + 7, 9, 12, 8, 13, 11, 17, 10, 6, 6, + 19, 18, 20, 14, 16, 6, 6, 6, 6, 6, + 0, 1, 2, 4, 3, 5, 17, 2, 2, 2, + 27, 15, 15, 27}, + 6 +}; + +/** Older Apple IIGS AGI instrument set. Used only by Space Quest I (AGI v1.002). */ +static const InstrumentSetInfo instSetV1 = { + 1192, 26, "7ee16bbc135171ffd6b9120cc7ff1af2", "edd3bf8905d9c238e02832b732fb2e18", progToInstMappingV1 +}; + +/** Newer Apple IIGS AGI instrument set (AGI v1.003+). Used by all others than Space Quest I. */ +static const InstrumentSetInfo instSetV2 = { + 1292, 28, "b7d428955bb90721996de1cbca25e768", "c05fb0b0e11deefab58bc68fbd2a3d07", progToInstMappingV2 +}; + +/** Information about different Apple IIGS AGI executables. */ +static const IIgsExeInfo IIgsExeInfos[] = { + {GID_SQ1, "SQ", 0x1002, 138496, 0x80AD, instSetV1}, + {GID_LSL1, "LL", 0x1003, 141003, 0x844E, instSetV2}, + {GID_AGIDEMO, "DEMO", 0x1005, 141884, 0x8469, instSetV2}, + {GID_KQ1, "KQ", 0x1006, 141894, 0x8469, instSetV2}, + {GID_PQ1, "PQ", 0x1007, 141882, 0x8469, instSetV2}, + {GID_MIXEDUP, "MG", 0x1013, 142552, 0x84B7, instSetV2}, + {GID_KQ2, "KQ2", 0x1013, 143775, 0x84B7, instSetV2}, + {GID_KQ3, "KQ3", 0x1014, 144312, 0x84B7, instSetV2}, + {GID_SQ2, "SQ2", 0x1014, 107882, 0x6563, instSetV2}, + {GID_MH1, "MH", 0x2004, 147678, 0x8979, instSetV2}, + {GID_KQ4, "KQ4", 0x2006, 147652, 0x8979, instSetV2}, + {GID_BC, "BC", 0x3001, 148192, 0x8979, instSetV2}, + {GID_GOLDRUSH, "GR", 0x3003, 148268, 0x8979, instSetV2} +}; + +/** + * Finds information about an Apple IIGS AGI executable based on the game ID. + * @return A non-null IIgsExeInfo pointer if successful, otherwise NULL. + */ +const IIgsExeInfo *SoundGen2GS::getIIgsExeInfo(enum AgiGameID gameid) const { + for (int i = 0; i < ARRAYSIZE(IIgsExeInfos); i++) + if (IIgsExeInfos[i].gameid == gameid) + return &IIgsExeInfos[i]; + return NULL; +} + +bool SoundGen2GS::loadInstrumentHeaders(const Common::FSNode &exePath, const IIgsExeInfo &exeInfo) { + bool loadedOk = false; // Was loading successful? + Common::File file; + + // Open the executable file and check that it has correct size + file.open(exePath); + if (file.size() != (int32)exeInfo.exeSize) { + debugC(3, kDebugLevelSound, "Apple IIGS executable (%s) has wrong size (Is %d, should be %d)", + exePath.getPath().c_str(), file.size(), exeInfo.exeSize); + } + + // Read the whole executable file into memory + Common::SharedPtr<Common::MemoryReadStream> data(file.readStream(file.size())); + file.close(); + + // Check that we got enough data to be able to parse the instruments + if (data && data->size() >= (int32)(exeInfo.instSetStart + exeInfo.instSet.byteCount)) { + // Check instrument set's length (The info's saved in the executable) + data->seek(exeInfo.instSetStart - 4); + uint16 instSetByteCount = data->readUint16LE(); + if (instSetByteCount != exeInfo.instSet.byteCount) { + debugC(3, kDebugLevelSound, "Wrong instrument set size (Is %d, should be %d) in Apple IIGS executable (%s)", + instSetByteCount, exeInfo.instSet.byteCount, exePath.getPath().c_str()); + } + + // Check instrument set's md5sum + data->seek(exeInfo.instSetStart); + + char md5str[32+1]; + Common::md5_file_string(*data, md5str, exeInfo.instSet.byteCount); + if (scumm_stricmp(md5str, exeInfo.instSet.md5)) { + warning("Unknown Apple IIGS instrument set (md5: %s) in %s, trying to use it nonetheless", + md5str, exePath.getPath().c_str()); + } + + // Read in the instrument set one instrument at a time + data->seek(exeInfo.instSetStart); + + // Load the instruments + _instruments.clear(); + _instruments.reserve(exeInfo.instSet.instCount); + + IIgsInstrumentHeader instrument; + for (uint i = 0; i < exeInfo.instSet.instCount; i++) { + if (!instrument.read(*data)) { + warning("Error loading Apple IIGS instrument (%d. of %d) from %s, not loading more instruments", + i + 1, exeInfo.instSet.instCount, exePath.getPath().c_str()); + break; + } + _instruments.push_back(instrument); // Add the successfully loaded instrument to the instruments array + } + + // Loading was successful only if all instruments were loaded successfully + loadedOk = (_instruments.size() == exeInfo.instSet.instCount); + } else // Couldn't read enough data from the executable file + warning("Error loading instruments from Apple IIGS executable (%s)", exePath.getPath().c_str()); + + return loadedOk; +} + +bool SoundGen2GS::loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo &exeInfo) { + Common::File file; + + // Open the wave file and read it into memory + file.open(wavePath); + Common::SharedPtr<Common::MemoryReadStream> uint8Wave(file.readStream(file.size())); + file.close(); + + // Check that we got the whole wave file + if (uint8Wave && uint8Wave->size() == SIERRASTANDARD_SIZE) { + // Check wave file's md5sum + char md5str[32+1]; + Common::md5_file_string(*uint8Wave, md5str, SIERRASTANDARD_SIZE); + if (scumm_stricmp(md5str, exeInfo.instSet.waveFileMd5)) { + warning("Unknown Apple IIGS wave file (md5: %s, game: %s).\n" \ + "Please report the information on the previous line to the ScummVM team.\n" \ + "Using the wave file as it is - music may sound weird", md5str, exeInfo.exePrefix); + } + + uint8Wave->seek(0); // Seek wave to its start + // Convert the wave file from 8-bit unsigned to 8-bit signed and save the result + _wave.resize(uint8Wave->size()); + return convertWave(*uint8Wave, _wave.begin(), uint8Wave->size()); + } else { // Couldn't read the wave file or it had incorrect size + warning("Error loading Apple IIGS wave file (%s), not loading instruments", wavePath.getPath().c_str()); + return false; + } +} + +} // End of namespace Agi diff --git a/engines/agi/sound_2gs.h b/engines/agi/sound_2gs.h new file mode 100644 index 0000000000..12dede0b69 --- /dev/null +++ b/engines/agi/sound_2gs.h @@ -0,0 +1,353 @@ +/* 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 AGI_SOUND_2GS_H +#define AGI_SOUND_2GS_H + +#include "common/frac.h" +#include "sound/audiostream.h" + +namespace Agi { + +#define BUFFER_SIZE 410 + +// Apple IIGS MIDI uses 60 ticks per second (Based on tests with Apple IIGS +// KQ1 and SQ1 under MESS 0.124a). So we make the audio buffer size to be a +// 1/60th of a second in length. That should be getSampleRate() / 60 samples +// in length but as getSampleRate() is always 22050 at the moment we just use +// the hardcoded value of 368 (22050/60 = 367.5 which rounds up to 368). +// FIXME: Use getSampleRate() / 60 rather than a hardcoded value +#define IIGS_BUFFER_SIZE 368 + +// MIDI command values (Shifted right by 4 so they're in the lower nibble) +#define MIDI_CMD_NOTE_OFF 0x08 +#define MIDI_CMD_NOTE_ON 0x09 +#define MIDI_CMD_CONTROLLER 0x0B +#define MIDI_CMD_PROGRAM_CHANGE 0x0C +#define MIDI_CMD_PITCH_WHEEL 0x0E +// Whole MIDI byte values (Command and channel info together) +#define MIDI_BYTE_STOP_SEQUENCE 0xFC +#define MIDI_BYTE_TIMER_SYNC 0xF8 + +struct IIgsEnvelopeSegment { + uint8 bp; + uint16 inc; ///< 8b.8b fixed point, very probably little endian +}; + +#define ENVELOPE_SEGMENT_COUNT 8 +struct IIgsEnvelope { + IIgsEnvelopeSegment seg[ENVELOPE_SEGMENT_COUNT]; + + /** Reads an Apple IIGS envelope from then given stream. */ + bool read(Common::SeekableReadStream &stream); +}; + +// 2**(1/12) i.e. the 12th root of 2 +#define SEMITONE 1.059463094359295 + +// C6's frequency is A4's (440 Hz) frequency but one full octave and three semitones higher +// i.e. C6_FREQ = 440 * pow(2.0, 15/12.0) +#define C6_FREQ 1046.502261202395 + +// Size of the SIERRASTANDARD file (i.e. the wave file i.e. the sample data used by the instruments). +#define SIERRASTANDARD_SIZE 65536 + +// Maximum number of instruments in an Apple IIGS instrument set. +// Chosen empirically based on Apple IIGS AGI game data, increase if needed. +#define MAX_INSTRUMENTS 28 + +struct IIgsWaveInfo { + uint8 top; + uint addr; + uint size; +// Oscillator channel +#define OSC_CHANNEL_RIGHT 0 +#define OSC_CHANNEL_LEFT 1 + uint channel; +// Oscillator mode +#define OSC_MODE_LOOP 0 +#define OSC_MODE_ONESHOT 1 +#define OSC_MODE_SYNC_AM 2 +#define OSC_MODE_SWAP 3 + uint mode; + bool halt; + int16 relPitch; ///< Relative pitch in semitones (Signed 8b.8b fixed point) + + /** Reads an Apple IIGS wave information structure from the given stream. */ + bool read(Common::SeekableReadStream &stream, bool ignoreAddr = false); + bool finalize(Common::SeekableReadStream &uint8Wave); +}; + +// Number of waves per Apple IIGS sound oscillator +#define WAVES_PER_OSCILLATOR 2 + +/** An Apple IIGS sound oscillator. Consists always of two waves. */ +struct IIgsOscillator { + IIgsWaveInfo waves[WAVES_PER_OSCILLATOR]; + + bool finalize(Common::SeekableReadStream &uint8Wave); +}; + +// Maximum number of oscillators in an Apple IIGS instrument. +// Chosen empirically based on Apple IIGS AGI game data, increase if needed. +#define MAX_OSCILLATORS 4 + +/** An Apple IIGS sound oscillator list. */ +struct IIgsOscillatorList { + uint count; ///< Oscillator count + IIgsOscillator osc[MAX_OSCILLATORS]; ///< The oscillators + + /** Indexing operators for easier access to the oscillators. */ + const IIgsOscillator &operator()(uint index) const { return osc[index]; } + IIgsOscillator &operator()(uint index) { return osc[index]; } + + /** Reads an Apple IIGS oscillator list from the given stream. */ + bool read(Common::SeekableReadStream &stream, uint oscillatorCount, bool ignoreAddr = false); + bool finalize(Common::SeekableReadStream &uint8Wave); +}; + +struct IIgsInstrumentHeader { + IIgsEnvelope env; + uint8 relseg; + uint8 bendrange; + uint8 vibdepth; + uint8 vibspeed; + IIgsOscillatorList oscList; + + /** + * Read an Apple IIGS instrument header from the given stream. + * @param stream The source stream from which to read the data. + * @param ignoreAddr Should we ignore wave infos' wave address variable's value? + * @return True if successful, false otherwise. + */ + bool read(Common::SeekableReadStream &stream, bool ignoreAddr = false); + bool finalize(Common::SeekableReadStream &uint8Wave); +}; + +struct IIgsSampleHeader { + uint16 type; + uint8 pitch; ///< Logarithmic, base is 2**(1/12), unknown multiplier (Possibly in range 1040-1080) + uint8 unknownByte_Ofs3; // 0x7F in Gold Rush's sound resource 60, 0 in all others. + uint8 volume; ///< Current guess: Logarithmic in 6 dB steps + uint8 unknownByte_Ofs5; ///< 0 in all tested samples. + uint16 instrumentSize; ///< Little endian. 44 in all tested samples. A guess. + uint16 sampleSize; ///< Little endian. Accurate in all tested samples excluding Manhunter I's sound resource 16. + IIgsInstrumentHeader instrument; + + /** + * Read an Apple IIGS AGI sample header from the given stream. + * @param stream The source stream from which to read the data. + * @return True if successful, false otherwise. + */ + bool read(Common::SeekableReadStream &stream); + bool finalize(Common::SeekableReadStream &uint8Wave); +}; + +struct IIgsChannelInfo { + const IIgsInstrumentHeader *ins; ///< Instrument info + const int8 *relocatedSample; ///< Source sample data (8-bit signed format) using relocation + const int8 *unrelocatedSample; ///< Source sample data (8-bit signed format) without relocation + frac_t pos; ///< Current sample position + frac_t posAdd; ///< Current sample position adder (Calculated using note, vibrato etc) + uint8 origNote; ///< The original note without the added relative pitch + frac_t note; ///< Note (With the added relative pitch) + frac_t vol; ///< Current volume (Takes both channel volume and enveloping into account) + frac_t chanVol; ///< Channel volume + frac_t startEnvVol; ///< Starting envelope volume + frac_t envVol; ///< Current envelope volume + uint envSeg; ///< Current envelope segment + uint size; ///< Sample size + bool loop; ///< Should we loop the sample? + bool end; ///< Has the playing ended? + + void rewind(); ///< Rewinds the sound playing on this channel to its start + void setChannelVolume(uint8 volume); ///< Sets the channel volume + void setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample); ///< Sets the instrument to be used on this channel + void noteOn(uint8 noteParam, uint8 velocity); ///< Starts playing a note on this channel + void noteOff(uint8 velocity); ///< Releases the note on this channel + void stop(); ///< Stops the note playing on this channel instantly + bool playing(); ///< Is there a note playing on this channel? +}; + +class IIgsMidi : public AgiSound { +public: + IIgsMidi(uint8 *data, uint32 len, int resnum, SoundMgr &manager); + ~IIgsMidi() { if (_data != NULL) free(_data); } + virtual uint16 type() { return _type; } + virtual const uint8 *getPtr() { return _ptr; } + virtual void setPtr(const uint8 *ptr) { _ptr = ptr; } + virtual void rewind() { _ptr = _data + 2; _midiTicks = _soundBufTicks = 0; } +protected: + uint8 *_data; ///< Raw sound resource data + const uint8 *_ptr; ///< Pointer to the current position in the MIDI data + uint32 _len; ///< Length of the raw sound resource + uint16 _type; ///< Sound resource type +public: + uint _midiTicks; ///< MIDI song position in ticks (1/60ths of a second) + uint _soundBufTicks; ///< Sound buffer position in ticks (1/60ths of a second) +}; + +class IIgsSample : public AgiSound { +public: + IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager); + ~IIgsSample() { delete[] _sample; } + virtual uint16 type() { return _header.type; } + const IIgsSampleHeader &getHeader() const { return _header; } + const int8 *getSample() const { return _sample; } +protected: + IIgsSampleHeader _header; ///< Apple IIGS AGI sample header + int8 *_sample; ///< Sample data (8-bit signed format) +}; + +/** Apple IIGS MIDI program change to instrument number mapping. */ +struct MidiProgramChangeMapping { + byte midiProgToInst[44]; ///< Lookup table for the MIDI program number to instrument number mapping + byte undefinedInst; ///< The undefined instrument number + + // Maps the MIDI program number to an instrument number + byte map(uint midiProg) const { + return midiProg < ARRAYSIZE(midiProgToInst) ? midiProgToInst[midiProg] : undefinedInst; + } +}; + +/** Apple IIGS AGI instrument set information. */ +struct InstrumentSetInfo { + uint byteCount; ///< Length of the whole instrument set in bytes + uint instCount; ///< Amount of instrument in the set + const char *md5; ///< MD5 hex digest of the whole instrument set + const char *waveFileMd5; ///< MD5 hex digest of the wave file (i.e. the sample data used by the instruments) + const MidiProgramChangeMapping &progToInst; ///< Program change to instrument number mapping +}; + +/** Apple IIGS AGI executable file information. */ +struct IIgsExeInfo { + enum AgiGameID gameid; ///< Game ID + const char *exePrefix; ///< Prefix of the Apple IIGS AGI executable (e.g. "SQ", "PQ", "KQ4" etc) + uint agiVer; ///< Apple IIGS AGI version number, not strictly needed + uint exeSize; ///< Size of the Apple IIGS AGI executable file in bytes + uint instSetStart; ///< Starting offset of the instrument set inside the executable file + const InstrumentSetInfo &instSet; ///< Information about the used instrument set +}; + +class IIgsMidiChannel { +public: + IIgsMidiChannel() : _instrument(0), _sample(0), _volume(0) {} + uint activeSounds() const; ///< How many active sounds are playing? + void setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample); + void setVolume(uint8 volume); + void noteOff(uint8 note, uint8 velocity); + void noteOn(uint8 note, uint8 velocity); + void stopSounds(); ///< Clears the channel of any sounds + void removeStoppedSounds(); ///< Removes all stopped sounds from this MIDI channel +public: + typedef Common::Array<IIgsChannelInfo>::const_iterator const_iterator; + typedef Common::Array<IIgsChannelInfo>::iterator iterator; + Common::Array<IIgsChannelInfo> _gsChannels; ///< Apple IIGS channels playing on this MIDI channel +protected: + const IIgsInstrumentHeader *_instrument; ///< Instrument used on this MIDI channel + const int8 *_sample; ///< Sample data used on this MIDI channel + uint8 _volume; ///< MIDI controller number 7 (Volume) +}; + +class SoundGen2GS : public SoundGen, public Audio::AudioStream { +public: + SoundGen2GS(AgiEngine *vm, Audio::Mixer *pMixer); + ~SoundGen2GS(); + + void play(int resnum); + void stop(void); + + // AudioStream API + int readBuffer(int16 *buffer, const int numSamples); + + bool isStereo() const { + return false; + } + + bool endOfData() const { + return false; + } + + int getRate() const { + // FIXME: Ideally, we should use _sampleRate. + return 22050; + } + +private: + bool _disabledMidi; + int _playingSound; + bool _playing; + + int16 *_sndBuffer; + +/** + * Class for managing Apple IIGS sound channels. + * TODO: Check what instruments are used by default on the MIDI channels + * FIXME: Some instrument choices sound wrong + */ +private: + typedef Common::Array<IIgsMidiChannel>::const_iterator const_iterator; + typedef Common::Array<IIgsMidiChannel>::iterator iterator; + static const uint kSfxMidiChannel = 0; ///< The MIDI channel used for playing sound effects + + bool loadInstruments(); + const IIgsExeInfo *getIIgsExeInfo(enum AgiGameID gameid) const; + + void setProgramChangeMapping(const MidiProgramChangeMapping *mapping); + bool loadInstrumentHeaders(const Common::FSNode &exePath, const IIgsExeInfo &exeInfo); + bool loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo &exeInfo); + + // Miscellaneous methods + void fillAudio(int16 *stream, uint len); + uint32 mixSound(); + void playSound(); + uint activeSounds() const; ///< How many active sounds are playing? + void stopSounds(); ///< Stops all sounds + void removeStoppedSounds(); ///< Removes all stopped sounds from the MIDI channels + + // For playing Apple IIGS AGI samples (Sound effects etc) + bool playSampleSound(const IIgsSampleHeader &sampleHeader, const int8 *sample); + void playMidiSound(); + void playSampleSound(); + + // MIDI commands + void midiNoteOff(uint8 channel, uint8 note, uint8 velocity); + void midiNoteOn(uint8 channel, uint8 note, uint8 velocity); + void midiController(uint8 channel, uint8 controller, uint8 value); + void midiProgramChange(uint8 channel, uint8 program); + void midiPitchWheel(uint8 wheelPos); + //protected: + const IIgsInstrumentHeader* getInstrument(uint8 program) const; + //public: + Common::Array<IIgsMidiChannel> _midiChannels; ///< Information about each MIDI channel + //protected: + Common::Array<int8> _wave; ///< Sample data used by the Apple IIGS MIDI instruments + const MidiProgramChangeMapping *_midiProgToInst; ///< MIDI program change to instrument number mapping + Common::Array<IIgsInstrumentHeader> _instruments; ///< Instruments used by the Apple IIGS AGI +}; + +} // End of namespace Agi + +#endif /* AGI_SOUND_2GS_H */ diff --git a/engines/agi/sound_coco3.cpp b/engines/agi/sound_coco3.cpp new file mode 100644 index 0000000000..f054be0682 --- /dev/null +++ b/engines/agi/sound_coco3.cpp @@ -0,0 +1,80 @@ +/* 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 "agi/agi.h" + +#include "agi/sound_coco3.h" + +namespace Agi { + +static int cocoFrequencies[] = { + 130, 138, 146, 155, 164, 174, 184, 195, 207, 220, 233, 246, + 261, 277, 293, 311, 329, 349, 369, 391, 415, 440, 466, 493, + 523, 554, 587, 622, 659, 698, 739, 783, 830, 880, 932, 987, + 1046, 1108, 1174, 1244, 1318, 1396, 1479, 1567, 1661, 1760, 1864, 1975, + 2093, 2217, 2349, 2489, 2637, 2793, 2959, 3135, 3322, 3520, 3729, 3951 +}; + +SoundGenCoCo3::SoundGenCoCo3(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer) { +} + +SoundGenCoCo3::~SoundGenCoCo3() { +} + +void SoundGenCoCo3::play(int resnum) { + int i = cocoFrequencies[0]; // Silence warning + + i = i + 1; + +#if 0 + int i = 0; + CoCoNote note; + + do { + note.read(_chn[i].ptr); + + if (note.freq != 0xff) { + playNote(0, cocoFrequencies[note.freq], note.volume); + + uint32 start_time = _vm->_system->getMillis(); + + while (_vm->_system->getMillis() < start_time + note.duration) { + _vm->_system->updateScreen(); + + _vm->_system->delayMillis(10); + } + } + } while (note.freq != 0xff); +#endif +} + +void SoundGenCoCo3::stop() { +} + +int SoundGenCoCo3::readBuffer(int16 *buffer, const int numSamples) { + return numSamples; +} + +} // End of namespace Agi diff --git a/engines/agi/sound_coco3.h b/engines/agi/sound_coco3.h new file mode 100644 index 0000000000..b60f1937cd --- /dev/null +++ b/engines/agi/sound_coco3.h @@ -0,0 +1,73 @@ +/* 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 AGI_SOUND_COCO3_H +#define AGI_SOUND_COCO3_H + +#include "sound/audiostream.h" + +namespace Agi { + +struct CoCoNote { + uint8 freq; + uint8 volume; + uint16 duration; ///< Note duration + + /** Reads a CoCoNote through the given pointer. */ + void read(const uint8 *ptr) { + freq = *ptr; + volume = *(ptr + 1); + duration = READ_LE_UINT16(ptr + 2); + } +}; + +class SoundGenCoCo3 : public SoundGen, public Audio::AudioStream { +public: + SoundGenCoCo3(AgiEngine *vm, Audio::Mixer *pMixer); + ~SoundGenCoCo3(); + + void play(int resnum); + void stop(void); + + // AudioStream API + int readBuffer(int16 *buffer, const int numSamples); + + bool isStereo() const { + return false; + } + + bool endOfData() const { + return false; + } + + int getRate() const { + // FIXME: Ideally, we should use _sampleRate. + return 22050; + } +}; + +} // End of namespace Agi + +#endif /* AGI_SOUND_COCO3_H */ diff --git a/engines/agi/sound_midi.cpp b/engines/agi/sound_midi.cpp new file mode 100644 index 0000000000..57c5d54b27 --- /dev/null +++ b/engines/agi/sound_midi.cpp @@ -0,0 +1,345 @@ +/* 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$ + * + */ + +// Code is based on: +// +// A very simple program, that converts an AGI-song into a MIDI-song. +// Feel free to use it for anything. +// +// The default instrument is "piano" for all the channels, what gives +// good results on most games. But I found, that some songs are interesting +// with other instruments. If you want to experiment, modify the "instr" +// array. +// +// Timing is not perfect, yet. It plays correct, when I use the +// Gravis-Midiplayer, but the songs are too fast when I use playmidi on +// Linux. +// +// Original program developed by Jens. Christian Restemeier +// + +// MIDI and digital music class + +#include "sound/audiostream.h" +#include "sound/mididrv.h" +#include "sound/midiparser.h" +#include "common/config-manager.h" +#include "common/file.h" +#include "common/stream.h" + +#include "agi/agi.h" + +#include "agi/sound.h" +#include "agi/sound_midi.h" + +#define SPEED_FACTOR 6 + +namespace Agi { + +static uint32 convertSND2MIDI(byte *snddata, byte **data); + +MIDISound::MIDISound(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) { + _data = data; // Save the resource pointer + _len = len; // Save the resource's length + _type = READ_LE_UINT16(data); // Read sound resource's type + _isValid = (_type == AGI_SOUND_4CHN) && (_data != NULL) && (_len >= 2); + + if (!_isValid) // Check for errors + warning("Error creating MIDI sound from resource %d (Type %d, length %d)", resnum, _type, len); +} + +SoundGenMIDI::SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer), _parser(0), _isPlaying(false), _passThrough(false), _isGM(false) { + DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB); + _driver = MidiDriver::createMidi(dev); + + memset(_channel, 0, sizeof(_channel)); + memset(_channelVolume, 255, sizeof(_channelVolume)); + _masterVolume = 0; + this->open(); + _smfParser = MidiParser::createParser_SMF(); + _midiMusicData = NULL; +} + +SoundGenMIDI::~SoundGenMIDI() { + _driver->setTimerCallback(NULL, NULL); + stop(); + this->close(); + _smfParser->setMidiDriver(NULL); + delete _smfParser; + delete[] _midiMusicData; +} + +void SoundGenMIDI::setChannelVolume(int channel) { + int newVolume = _channelVolume[channel] * _masterVolume / 255; + _channel[channel]->volume(newVolume); +} + +void SoundGenMIDI::setVolume(int volume) { + Common::StackLock lock(_mutex); + + volume = CLIP(volume, 0, 255); + if (_masterVolume == volume) + return; + _masterVolume = volume; + + for (int i = 0; i < 16; ++i) { + if (_channel[i]) { + setChannelVolume(i); + } + } +} + +int SoundGenMIDI::open() { + // Don't ever call open without first setting the output driver! + if (!_driver) + return 255; + + int ret = _driver->open(); + if (ret) + return ret; + + _driver->setTimerCallback(this, &onTimer); + return 0; +} + +void SoundGenMIDI::close() { + stop(); + if (_driver) + _driver->close(); + _driver = 0; +} + +void SoundGenMIDI::send(uint32 b) { + if (_passThrough) { + _driver->send(b); + return; + } + + byte channel = (byte)(b & 0x0F); + if ((b & 0xFFF0) == 0x07B0) { + // Adjust volume changes by master volume + byte volume = (byte)((b >> 16) & 0x7F); + _channelVolume[channel] = volume; + volume = volume * _masterVolume / 255; + b = (b & 0xFF00FFFF) | (volume << 16); + } else if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) { + b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8; + } + else if ((b & 0xFFF0) == 0x007BB0) { + //Only respond to All Notes Off if this channel + //has currently been allocated + if (_channel[b & 0x0F]) + return; + } + + if (!_channel[channel]) { + _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel(); + // If a new channel is allocated during the playback, make sure + // its volume is correctly initialized. + if (_channel[channel]) + setChannelVolume(channel); + } + + if (_channel[channel]) + _channel[channel]->send(b); +} + +void SoundGenMIDI::metaEvent(byte type, byte *data, uint16 length) { + + switch (type) { + case 0x2F: // End of Track + stop(); + _vm->_sound->soundIsFinished(); + break; + default: + //warning("Unhandled meta event: %02x", type); + break; + } +} + +void SoundGenMIDI::onTimer(void *refCon) { + SoundGenMIDI *music = (SoundGenMIDI *)refCon; + Common::StackLock lock(music->_mutex); + + if (music->_parser) + music->_parser->onTimer(); +} + +void SoundGenMIDI::play(int resnum) { + MIDISound *track; + + stop(); + + _isGM = true; + + track = (MIDISound *)_vm->_game.sounds[resnum]; + + // Convert AGI Sound data to MIDI + int midiMusicSize = convertSND2MIDI(track->_data, &_midiMusicData); + + if (_smfParser->loadMusic(_midiMusicData, midiMusicSize)) { + MidiParser *parser = _smfParser; + parser->setTrack(0); + parser->setMidiDriver(this); + parser->setTimerRate(getBaseTempo()); + parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); + + _parser = parser; + + syncVolume(); + + _isPlaying = true; + } +} + +void SoundGenMIDI::stop() { + Common::StackLock lock(_mutex); + + if (!_isPlaying) + return; + + _isPlaying = false; + if (_parser) { + _parser->unloadMusic(); + _parser = NULL; + } +} + +void SoundGenMIDI::pause() { + setVolume(-1); + _isPlaying = false; +} + +void SoundGenMIDI::resume() { + syncVolume(); + _isPlaying = true; +} + +void SoundGenMIDI::syncVolume() { + int volume = ConfMan.getInt("music_volume"); + if (ConfMan.getBool("mute")) { + volume = -1; + } + setVolume(volume); +} + +/* channel / intrument setup: */ + +/* most songs are good with this: */ +unsigned char instr[] = {0, 0, 0}; + +/* cool for sq2: +unsigned char instr[] = {50, 51, 19}; +*/ + +static void writeDelta(Common::MemoryWriteStreamDynamic *st, int32 delta) { + int32 i; + + i = delta >> 21; if (i > 0) st->writeByte((i & 127) | 128); + i = delta >> 14; if (i > 0) st->writeByte((i & 127) | 128); + i = delta >> 7; if (i > 0) st->writeByte((i & 127) | 128); + st->writeByte(delta & 127); +} + +static uint32 convertSND2MIDI(byte *snddata, byte **data) { + int32 lp, ep; + int n; + double ll; + + Common::MemoryWriteStreamDynamic st; + + ll = log10(pow(2.0, 1.0 / 12.0)); + + /* Header */ + st.write("MThd", 4); + st.writeUint32BE(6); + st.writeUint16BE(1); /* mode */ + st.writeUint16BE(3); /* number of tracks */ + st.writeUint16BE(192); /* ticks / quarter */ + + for (n = 0; n < 3; n++) { + uint16 start, end, pos; + + st.write("MTrk", 4); + lp = st.pos(); + st.writeUint32BE(0); /* chunklength */ + writeDelta(&st, 0); /* set instrument */ + st.writeByte(0xc0 + n); + st.writeByte(instr[n]); + start = snddata[n * 2 + 0] | (snddata[n * 2 + 1] << 8); + end = ((snddata[n * 2 + 2] | (snddata[n * 2 + 3] << 8))) - 5; + + for (pos = start; pos < end; pos += 5) { + uint16 freq, dur; + dur = (snddata[pos + 0] | (snddata[pos + 1] << 8)) * SPEED_FACTOR; + freq = ((snddata[pos + 2] & 0x3F) << 4) + (snddata[pos + 3] & 0x0F); + if (snddata[pos + 2] > 0) { + double fr; + int note; + /* I don't know, what frequency equals midi note 0 ... */ + /* This moves the song 4 octaves down: */ + fr = (log10(111860.0 / (double)freq) / ll) - 48; + note = (int)floor(fr + 0.5); + if (note < 0) note = 0; + if (note > 127) note = 127; + /* note on */ + writeDelta(&st, 0); + st.writeByte(144 + n); + st.writeByte(note); + st.writeByte(100); + /* note off */ + writeDelta(&st, dur); + st.writeByte(128 + n); + st.writeByte(note); + st.writeByte(0); + } else { + /* note on */ + writeDelta(&st, 0); + st.writeByte(144 + n); + st.writeByte(0); + st.writeByte(0); + /* note off */ + writeDelta(&st, dur); + st.writeByte(128 + n); + st.writeByte(0); + st.writeByte(0); + } + } + writeDelta(&st, 0); + st.writeByte(0xff); + st.writeByte(0x2f); + st.writeByte(0x0); + ep = st.pos(); + st.seek(lp, SEEK_SET); + st.writeUint32BE((ep - lp) - 4); + st.seek(ep, SEEK_SET); + } + + *data = st.getData(); + + return st.pos(); +} + +} // End of namespace Agi diff --git a/engines/agi/sound_midi.h b/engines/agi/sound_midi.h new file mode 100644 index 0000000000..26b75e0d70 --- /dev/null +++ b/engines/agi/sound_midi.h @@ -0,0 +1,114 @@ +/* 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$ + * + */ + +// Music class + +#ifndef AGI_SOUND_MIDI_H +#define AGI_SOUND_MIDI_H + +#include "sound/mididrv.h" +#include "sound/midiparser.h" +#include "common/mutex.h" + +namespace Agi { + +class MIDISound : public AgiSound { +public: + MIDISound(uint8 *data, uint32 len, int resnum, SoundMgr &manager); + ~MIDISound() { free(_data); } + virtual uint16 type() { return _type; } + uint8 *_data; ///< Raw sound resource data + uint32 _len; ///< Length of the raw sound resource + +protected: + uint16 _type; ///< Sound resource type +}; + +class SoundGenMIDI : public SoundGen, public MidiDriver { +public: + SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer); + ~SoundGenMIDI(); + + void play(int resnum); + void stop(); + + bool isPlaying() { return _isPlaying; } + void setPlaying(bool playing) { _isPlaying = playing; } + + void setVolume(int volume); + int getVolume() { return _masterVolume; } + void syncVolume(); + + void setNativeMT32(bool b) { _nativeMT32 = b; } + bool hasNativeMT32() { return _nativeMT32; } + void pause(); + void resume(); + void setLoop(bool loop) { _looping = loop; } + void setPassThrough(bool b) { _passThrough = b; } + + void setGM(bool isGM) { _isGM = isGM; } + + // MidiDriver interface implementation + int open(); + void close(); + void send(uint32 b); + + void metaEvent(byte type, byte *data, uint16 length); + + void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { } + uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; } + + // Channel allocation functions + MidiChannel *allocateChannel() { return 0; } + MidiChannel *getPercussionChannel() { return 0; } + + MidiParser *_parser; + Common::Mutex _mutex; + +private: + + static void onTimer(void *data); + void setChannelVolume(int channel); + + MidiChannel *_channel[16]; + MidiDriver *_driver; + MidiParser *_smfParser; + byte _channelVolume[16]; + bool _nativeMT32; + bool _isGM; + bool _passThrough; + + bool _isPlaying; + bool _looping; + byte _masterVolume; + + byte *_midiMusicData; + + SoundMgr *_manager; +}; + +} // End of namespace Agi + +#endif diff --git a/engines/agi/sound_pcjr.cpp b/engines/agi/sound_pcjr.cpp new file mode 100644 index 0000000000..b9d701d7f7 --- /dev/null +++ b/engines/agi/sound_pcjr.cpp @@ -0,0 +1,512 @@ +/* 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$ + * + */ + +/* Heavily based on code from NAGI + * + * COPYRIGHT AND PERMISSION NOTICE + * + * Copyright (c) 2001, 2001, 2002 Nick Sonneveld + * + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons + * to whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * + */ + +#include "agi/agi.h" +#include "agi/sound.h" +#include "agi/sound_pcjr.h" + +namespace Agi { + +// "fade out" or possibly "dissolve" +// v2.9xx +const int8 dissolveDataV2[] = { + -2, -3, -2, -1, + 0x00, 0x00, + 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x04, + 0x05, 0x05, 0x05, 0x05, + 0x06, 0x06, 0x06, 0x06, 0x06, + 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08, + 0x09, 0x09, 0x09, 0x09, + 0x0A, 0x0A, 0x0A, 0x0A, + 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0D, + -100 +}; + +// v3 +const int8 dissolveDataV3[] = { + -2, -3, -2, -1, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x04, 0x04, + 0x05, 0x05, 0x05, 0x05, 0x05, + 0x06, 0x06, 0x06, 0x06, 0x06, + 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08, + 0x09, 0x09, 0x09, 0x09, + 0x0A, 0x0A, 0x0A, 0x0A, + 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0D, + -100 +}; + + +SoundGenPCJr::SoundGenPCJr(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer) { + _chanAllocated = 10240; // preallocate something which will most likely fit + _chanData = (int16 *)malloc(_chanAllocated << 1); + + // Pick dissolve method + // + // 0 = no dissolve.. just play for as long as it's meant to be played + // this was used in older v2.4 and under games i THINK + // 1 = not used + // 2 = v2.9+ games used a shorter dissolve + // 3 (default) = v3 games used this dissolve pattern.. slightly longer + if (_vm->getVersion() >= 0x3000) + _dissolveMethod = 3; + else if (_vm->getVersion() >= 0x2900) + _dissolveMethod = 2; + else + _dissolveMethod = 0; + + _dissolveMethod = 3; + + _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); +} + +SoundGenPCJr::~SoundGenPCJr() { + free(_chanData); + + _mixer->stopHandle(_soundHandle); +} + +void SoundGenPCJr::play(int resnum) { + PCjrSound *pcjrSound = (PCjrSound *)_vm->_game.sounds[resnum]; + + for (int i = 0; i < CHAN_MAX; i++) { + _channel[i].data = pcjrSound->getVoicePointer(i % 4); + _channel[i].duration = 0; + _channel[i].avail = 0xffff; + _channel[i].dissolveCount = 0xFFFF; + _channel[i].attenuation = 0; + _channel[i].attenuationCopy = 0; + + _tchannel[i].avail = 1; + _tchannel[i].noteCount = 0; + _tchannel[i].freqCount = 250; + _tchannel[i].freqCountPrev = -1; + _tchannel[i].atten = 0xF; // silence + _tchannel[i].genType = kGenTone; + _tchannel[i].genTypePrev = -1; + } +} + +void SoundGenPCJr::stop(void) { + int i; + + for (i = 0; i < CHAN_MAX ; i++) { + _channel[i].avail = 0; + _tchannel[i].avail = 0; + } +} + +int SoundGenPCJr::volumeCalc(SndGenChan *chan) { + int8 attenuation, dissolveValue; + + const int8 *dissolveData; + + switch (_dissolveMethod) { + case 2: + dissolveData = dissolveDataV2; + break; + case 3: + default: + dissolveData = dissolveDataV3; + break; + } + + assert(chan); + + attenuation = chan->attenuation; + if (attenuation != 0x0F) { // != silence + if (chan->dissolveCount != 0xFFFF) { + dissolveValue = dissolveData[chan->dissolveCount]; + if (dissolveValue == -100) { // if at end of list + chan->dissolveCount = 0xFFFF; + chan->attenuation = chan->attenuationCopy; + attenuation = chan->attenuation; + } else { + chan->dissolveCount++; + + attenuation += dissolveValue; + if (attenuation < 0) + attenuation = 0; + if (attenuation > 0x0F) + attenuation = 0x0F; + + chan->attenuationCopy = attenuation; + + attenuation &= 0x0F; + attenuation += _vm->getvar(vVolume); + if (attenuation > 0x0F) + attenuation = 0x0F; + } + } + //if (computer_type == 2) && (attenuation < 8) + if (attenuation < 8) + attenuation += 2; + } + + return attenuation; +} + +// read the next channel data.. fill it in *tone +// if tone isn't touched.. it should be inited so it just plays silence +// return 0 if it's passing more data +// return -1 if it's passing nothing (end of data) +int SoundGenPCJr::getNextNote(int ch, Tone *tone) { + SndGenChan *chan; + const byte *data; + + assert(tone); + assert(ch < CHAN_MAX); + + if (!_vm->getflag(fSoundOn)) + return -1; + + chan = &_channel[ch]; + if (!chan->avail) + return -1; + + while ((chan->duration == 0) && (chan->duration != 0xFFFF)) { + data = chan->data; + + // read the duration of the note + chan->duration = READ_LE_UINT16(data); // duration + + // if it's 0 then it's not going to be played + // if it's 0xFFFF then the channel data has finished. + if ((chan->duration != 0) && (chan->duration != 0xFFFF)) { + // only tone channels dissolve + if ((ch != 3) && (_dissolveMethod != 0)) // != noise?? + chan->dissolveCount = 0; + + // attenuation (volume) + chan->attenuation = data[4] & 0xF; + + // frequency + if (ch < (CHAN_MAX - 1)) { + chan->freqCount = (uint16)data[2] & 0x3F; + chan->freqCount <<= 4; + chan->freqCount |= data[3] & 0x0F; + + chan->genType = kGenTone; + } else { + int noiseFreq; + + // check for white noise (1) or periodic (0) + chan->genType = (data[3] & 0x04) ? kGenWhite : kGenPeriod; + + noiseFreq = data[3] & 0x03; + + switch (noiseFreq) { + case 0: + chan->freqCount = 32; + break; + case 1: + chan->freqCount = 64; + break; + case 2: + chan->freqCount = 128; + break; + case 3: + chan->freqCount = _channel[2].freqCount * 2; + break; + } + } + } + // data now points to the next data seg-a-ment + chan->data += 5; + } + + if (chan->duration != 0xFFFF) { + tone->freqCount = chan->freqCount; + tone->atten = volumeCalc(chan); // calc volume, sent vol is different from saved vol + tone->type = chan->genType; + chan->duration--; + } else { + // kill channel + chan->avail = 0; + chan->attenuation = 0x0F; // silent + chan->attenuationCopy = 0x0F; // dunno really + + return -1; + } + + return 0; +} + +// Formulas for noise generator +// bit0 = output + +// noise feedback for white noise mode +#define FB_WNOISE 0x12000 // bit15.d(16bits) = bit0(out) ^ bit2 +//#define FB_WNOISE 0x14000 // bit15.d(16bits) = bit0(out) ^ bit1 +//#define FB_WNOISE 0x28000 // bit16.d(17bits) = bit0(out) ^ bit2 (same to AY-3-8910) +//#define FB_WNOISE 0x50000 // bit17.d(18bits) = bit0(out) ^ bit2 + +// noise feedback for periodic noise mode +// it is correct maybe (it was in the Megadrive sound manual) +//#define FB_PNOISE 0x10000 // 16bit rorate +#define FB_PNOISE 0x08000 + +// noise generator start preset (for periodic noise) +#define NG_PRESET 0x0f35 + +//#define WAVE_HEIGHT (0x7FFF) + +// Volume table. +// +// 2dB = 20*log(a/b) +// 10^(2/20)*b = a; +// value = 0x7fff; +// value /= 1.258925411794; +const int16 volTable[16] = { + 32767, 26027, 20674, 16422, 13044, 10361, 8230, 6537, 5193, 4125, 3276, 2602, 2067, 1642, 1304, 0 +}; + +#define FREQ_DIV 111844 +#define MULT FREQ_DIV + +// fill buff +int SoundGenPCJr::chanGen(int chan, int16 *stream, int len) { + ToneChan *tpcm; + Tone toneNew; + int fillSize; + int retVal; + + tpcm = &_tchannel[chan]; + + retVal = -1; + + while (len > 0) { + if (tpcm->noteCount <= 0) { + // get new tone data + toneNew.freqCount = 0; + toneNew.atten = 0xF; + toneNew.type = kGenTone; + if ((tpcm->avail) && (getNextNote(chan, &toneNew) == 0)) { + tpcm->atten = toneNew.atten; + tpcm->freqCount = toneNew.freqCount; + tpcm->genType = toneNew.type; + + // setup counters 'n stuff + // SAMPLE_RATE samples per sec.. tone changes 60 times per sec + tpcm->noteCount = SAMPLE_RATE / 60; + retVal = 0; + } else { + // if it doesn't return an + tpcm->genType = kGenSilence; + tpcm->noteCount = len; + tpcm->avail = 0; + } + } + + // write nothing + if ((tpcm->freqCount == 0) || (tpcm->atten == 0xf)) { + tpcm->genType = kGenSilence; + } + + // find which is smaller.. the buffer or the + fillSize = (tpcm->noteCount <= len) ? tpcm->noteCount : len; + + switch (tpcm->genType) { + case kGenTone: + fillSize = fillSquare(tpcm, stream, fillSize); + break; + case kGenPeriod: + case kGenWhite: + fillSize = fillNoise(tpcm, stream, fillSize); + break; + case kGenSilence: + default: + // fill with whitespace + memset(stream, 0, fillSize * sizeof(int16)); + break; + } + + tpcm->noteCount -= fillSize; + stream += fillSize; + len -= fillSize; + } + + return retVal; +} + +int SoundGenPCJr::fillSquare(ToneChan *t, int16 *buf, int len) { + int count; + + if (t->genType != t->genTypePrev) { + // make sure the freqCount is checked + t->freqCountPrev = -1; + t->sign = 1; + t->genTypePrev = t->genType; + } + + if (t->freqCount != t->freqCountPrev) { + //t->scale = (int)( (double)t->samp->freq*t->freqCount/FREQ_DIV * MULT + 0.5); + t->scale = (SAMPLE_RATE / 2) * t->freqCount; + t->count = t->scale; + t->freqCountPrev = t->freqCount; + } + + count = len; + + while (count > 0) { + *(buf++) = t->sign ? volTable[t->atten] : -volTable[t->atten]; + count--; + + // get next sample + t->count -= MULT; + while (t->count <= 0) { + t->sign ^= 1; + t->count += t->scale; + } + } + + return len; +} + +int SoundGenPCJr::fillNoise(ToneChan *t, int16 *buf, int len) { + int count; + + if (t->genType != t->genTypePrev) { + // make sure the freqCount is checked + t->freqCountPrev = -1; + t->genTypePrev = t->genType; + } + + if (t->freqCount != t->freqCountPrev) { + //t->scale = (int)( (double)t->samp->freq*t->freqCount/FREQ_DIV * MULT + 0.5); + t->scale = (SAMPLE_RATE / 2) * t->freqCount; + t->count = t->scale; + t->freqCountPrev = t->freqCount; + + t->feedback = (t->genType == kGenWhite) ? FB_WNOISE : FB_PNOISE; + // reset noise shifter + t->noiseState = NG_PRESET; + t->sign = t->noiseState & 1; + } + + count = len; + + while (count > 0) { + *(buf++) = t->sign ? volTable[t->atten] : -volTable[t->atten]; + count--; + + // get next sample + t->count -= MULT; + while (t->count <= 0) { + if (t->noiseState & 1) + t->noiseState ^= t->feedback; + + t->noiseState >>= 1; + t->sign = t->noiseState & 1; + t->count += t->scale; + } + } + + return len; +} + +int SoundGenPCJr::readBuffer(int16 *stream, const int len) { + int streamCount; + int16 *sPtr, *cPtr; + + if (_chanAllocated < len) { + free(_chanData); + _chanData = (int16 *)malloc(len << 1); + _chanAllocated = len; + } + memset(stream, 0, len << 1); + + assert(stream); + + bool finished = true; + + for (int i = 0; i < CHAN_MAX; i++) { + // get channel data(chan.userdata) + if (chanGen(i, _chanData, len) == 0) { + // divide by number of channels then add to stream + streamCount = len; + sPtr = stream; + cPtr = _chanData; + + while (streamCount--) + *(sPtr++) += *(cPtr++) / CHAN_MAX; + + finished = false; + } + } + + if (finished) + _vm->_sound->soundIsFinished(); + + return len; +} + +} // End of namespace Agi diff --git a/engines/agi/sound_pcjr.h b/engines/agi/sound_pcjr.h new file mode 100644 index 0000000000..fe0e762f4e --- /dev/null +++ b/engines/agi/sound_pcjr.h @@ -0,0 +1,127 @@ +/* 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 AGI_SOUND_PCJR_H +#define AGI_SOUND_PCJR_H + +#include "sound/audiostream.h" + +namespace Agi { + +#define CHAN_MAX 4 + +#define SAMPLE_RATE 22050 + +enum GenType { + kGenSilence, + kGenTone, + kGenPeriod, + kGenWhite +}; + +struct SndGenChan { + const byte *data; + uint16 duration; + uint16 avail; // turned on (1) but when the channel's data runs out, it's set to (0) + uint16 dissolveCount; + byte attenuation; + byte attenuationCopy; + + GenType genType; + + // for the sample mixer + int freqCount; +}; + +struct ToneChan { + int avail; + + int noteCount; // length of tone.. duration + + int freqCount; + int freqCountPrev; + int atten; // volume + + GenType genType; + int genTypePrev; + + int count; + int scale; + int sign; + unsigned int noiseState; /* noise generator */ + int feedback; /* noise feedback mask */ +}; + +struct Tone { + int freqCount; + int atten; + GenType type; +}; + +class SoundGenPCJr : public SoundGen, public Audio::AudioStream { +public: + SoundGenPCJr(AgiEngine *vm, Audio::Mixer *pMixer); + ~SoundGenPCJr(); + + void play(int resnum); + void stop(void); + + // AudioStream API + int readBuffer(int16 *buffer, const int numSamples); + + bool isStereo() const { + return false; + } + + bool endOfData() const { + return false; + } + + int getRate() const { + // FIXME: Ideally, we should use _sampleRate. + return 22050; + } + +private: + int getNextNote(int ch, Tone *tone); + int volumeCalc(SndGenChan *chan); + + int chanGen(int chan, int16 *stream, int len); + + int fillNoise(ToneChan *t, int16 *buf, int len); + int fillSquare(ToneChan *t, int16 *buf, int len); + +private: + SndGenChan _channel[CHAN_MAX]; + ToneChan _tchannel[CHAN_MAX]; + int16 *_chanData; + int _chanAllocated; + + int _dissolveMethod; +}; + +} // End of namespace Agi + +#endif /* AGI_SOUND_PCJR_H */ diff --git a/engines/agi/sound_sarien.cpp b/engines/agi/sound_sarien.cpp new file mode 100644 index 0000000000..08bdd47497 --- /dev/null +++ b/engines/agi/sound_sarien.cpp @@ -0,0 +1,357 @@ +/* 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/md5.h" +#include "common/config-manager.h" +#include "common/fs.h" +#include "common/random.h" +#include "common/str-array.h" + +#include "sound/mididrv.h" + +#include "agi/agi.h" + +#include "agi/sound_sarien.h" + +namespace Agi { + +#define USE_INTERPOLATION + +static const int16 waveformRamp[WAVEFORM_SIZE] = { + 0, 8, 16, 24, 32, 40, 48, 56, + 64, 72, 80, 88, 96, 104, 112, 120, + 128, 136, 144, 152, 160, 168, 176, 184, + 192, 200, 208, 216, 224, 232, 240, 255, + 0, -248, -240, -232, -224, -216, -208, -200, + -192, -184, -176, -168, -160, -152, -144, -136, + -128, -120, -112, -104, -96, -88, -80, -72, + -64, -56, -48, -40, -32, -24, -16, -8 // Ramp up +}; + +static const int16 waveformSquare[WAVEFORM_SIZE] = { + 255, 230, 220, 220, 220, 220, 220, 220, + 220, 220, 220, 220, 220, 220, 220, 220, + 220, 220, 220, 220, 220, 220, 220, 220, + 220, 220, 220, 220, 220, 220, 220, 110, + -255, -230, -220, -220, -220, -220, -220, -220, + -220, -220, -220, -220, -220, -220, -220, -220, + -220, -220, -220, -220, -220, -220, -220, -220, + -220, -220, -220, -110, 0, 0, 0, 0 // Square +}; + +static const int16 waveformMac[WAVEFORM_SIZE] = { + 45, 110, 135, 161, 167, 173, 175, 176, + 156, 137, 123, 110, 91, 72, 35, -2, + -60, -118, -142, -165, -170, -176, -177, -179, + -177, -176, -164, -152, -117, -82, -17, 47, + 92, 137, 151, 166, 170, 173, 171, 169, + 151, 133, 116, 100, 72, 43, -7, -57, + -99, -141, -156, -170, -174, -177, -178, -179, + -175, -172, -165, -159, -137, -114, -67, -19 +}; + +SoundGenSarien::SoundGenSarien(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer), _chn() { + _sndBuffer = (int16 *)calloc(2, BUFFER_SIZE); + + memset(_sndBuffer, 0, BUFFER_SIZE << 1); + _env = false; + _playingSound = -1; + _playing = false; + _useChorus = true; // FIXME: Currently always true? + + switch (_vm->_soundemu) { + case SOUND_EMU_NONE: + _waveform = waveformRamp; + _env = true; + break; + case SOUND_EMU_AMIGA: + case SOUND_EMU_PC: + _waveform = waveformSquare; + break; + case SOUND_EMU_MAC: + _waveform = waveformMac; + break; + } + + report("Initializing sound:\n"); + + report("sound: envelopes "); + if (_env) { + report("enabled (decay=%d, sustain=%d)\n", ENV_DECAY, ENV_SUSTAIN); + } else { + report("disabled\n"); + } + + _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); +} + +SoundGenSarien::~SoundGenSarien() { + _mixer->stopHandle(_soundHandle); + + free(_sndBuffer); +} + +int SoundGenSarien::readBuffer(int16 *buffer, const int numSamples) { + fillAudio(buffer, numSamples / 2); + + return numSamples; +} + +void SoundGenSarien::play(int resnum) { + AgiSoundEmuType type; + + type = (AgiSoundEmuType)_vm->_game.sounds[resnum]->type(); + + assert(type == AGI_SOUND_4CHN); + + _playingSound = resnum; + + PCjrSound *pcjrSound = (PCjrSound *) _vm->_game.sounds[resnum]; + + // Initialize channel info + for (int i = 0; i < NUM_CHANNELS; i++) { + _chn[i].type = type; + _chn[i].flags = AGI_SOUND_LOOP; + + if (_env) { + _chn[i].flags |= AGI_SOUND_ENVELOPE; + _chn[i].adsr = AGI_SOUND_ENV_ATTACK; + } + + _chn[i].ins = _waveform; + _chn[i].size = WAVEFORM_SIZE; + _chn[i].ptr = pcjrSound->getVoicePointer(i % 4); + _chn[i].timer = 0; + _chn[i].vol = 0; + _chn[i].end = 0; + } + + memset(_sndBuffer, 0, BUFFER_SIZE << 1); +} + +void SoundGenSarien::stop() { + _playingSound = -1; + + for (int i = 0; i < NUM_CHANNELS; i++) + stopNote(i); +} + +void SoundGenSarien::stopNote(int i) { + _chn[i].adsr = AGI_SOUND_ENV_RELEASE; + + if (_useChorus) { + // Stop chorus ;) + if (_chn[i].type == AGI_SOUND_4CHN && + _vm->_soundemu == SOUND_EMU_NONE && i < 3) { + stopNote(i + 4); + } + } +} + +void SoundGenSarien::playNote(int i, int freq, int vol) { + if (!_vm->getflag(fSoundOn)) + vol = 0; + else if (vol && _vm->_soundemu == SOUND_EMU_PC) + vol = 160; + + _chn[i].phase = 0; + _chn[i].freq = freq; + _chn[i].vol = vol; + _chn[i].env = 0x10000; + _chn[i].adsr = AGI_SOUND_ENV_ATTACK; + + if (_useChorus) { + // Add chorus ;) + if (_chn[i].type == AGI_SOUND_4CHN && + _vm->_soundemu == SOUND_EMU_NONE && i < 3) { + + int newfreq = freq * 1007 / 1000; + + if (freq == newfreq) + newfreq++; + + playNote(i + 4, newfreq, vol * 2 / 3); + } + } +} + +void SoundGenSarien::playSound() { + int i; + AgiNote note; + + if (_playingSound == -1) + return; + + _playing = false; + for (i = 0; i < (_vm->_soundemu == SOUND_EMU_PC ? 1 : 4); i++) { + _playing |= !_chn[i].end; + note.read(_chn[i].ptr); // Read a single note (Doesn't advance the pointer) + + if (_chn[i].end) + continue; + + if ((--_chn[i].timer) <= 0) { + stopNote(i); + + if (note.freqDiv != 0) { + int volume = (note.attenuation == 0x0F) ? 0 : (0xFF - note.attenuation * 2); + playNote(i, note.freqDiv * 10, volume); + } + + _chn[i].timer = note.duration; + + if (_chn[i].timer == 0xffff) { + _chn[i].end = 1; + _chn[i].vol = 0; + _chn[i].env = 0; + + if (_useChorus) { + // chorus + if (_chn[i].type == AGI_SOUND_4CHN && _vm->_soundemu == SOUND_EMU_NONE && i < 3) { + _chn[i + 4].vol = 0; + _chn[i + 4].env = 0; + } + } + } + _chn[i].ptr += 5; // Advance the pointer to the next note data (5 bytes per note) + } + } + + if (!_playing) { + _vm->_sound->soundIsFinished(); + + _playingSound = -1; + } +} + +uint32 SoundGenSarien::mixSound() { + register int i, p; + const int16 *src; + int c, b, m; + + memset(_sndBuffer, 0, BUFFER_SIZE << 1); + + if (!_playing || _playingSound == -1) + return BUFFER_SIZE; + + // Handle PCjr 4-channel sound mixing here + for (c = 0; c < NUM_CHANNELS; c++) { + if (!_chn[c].vol) + continue; + + m = _chn[c].flags & AGI_SOUND_ENVELOPE ? + _chn[c].vol * _chn[c].env >> 16 : _chn[c].vol; + + if (_chn[c].type != AGI_SOUND_4CHN || c != 3) { + src = _chn[c].ins; + + p = _chn[c].phase; + for (i = 0; i < BUFFER_SIZE; i++) { + b = src[p >> 8]; +#ifdef USE_INTERPOLATION + b += ((src[((p >> 8) + 1) % _chn[c].size] - src[p >> 8]) * (p & 0xff)) >> 8; +#endif + _sndBuffer[i] += (b * m) >> 4; + + p += (uint32) 118600 *4 / _chn[c].freq; + + // FIXME: Fingolfin asks: why is there a FIXME here? Please either clarify what + // needs fixing, or remove it! + // FIXME + if (_chn[c].flags & AGI_SOUND_LOOP) { + p %= _chn[c].size << 8; + } else { + if (p >= _chn[c].size << 8) { + p = _chn[c].vol = 0; + _chn[c].end = 1; + break; + } + } + + } + _chn[c].phase = p; + } else { + // Add white noise + for (i = 0; i < BUFFER_SIZE; i++) { + b = _vm->_rnd->getRandomNumber(255) - 128; + _sndBuffer[i] += (b * m) >> 4; + } + } + + switch (_chn[c].adsr) { + case AGI_SOUND_ENV_ATTACK: + // not implemented + _chn[c].adsr = AGI_SOUND_ENV_DECAY; + break; + case AGI_SOUND_ENV_DECAY: + if (_chn[c].env > _chn[c].vol * ENV_SUSTAIN + ENV_DECAY) { + _chn[c].env -= ENV_DECAY; + } else { + _chn[c].env = _chn[c].vol * ENV_SUSTAIN; + _chn[c].adsr = AGI_SOUND_ENV_SUSTAIN; + } + break; + case AGI_SOUND_ENV_SUSTAIN: + break; + case AGI_SOUND_ENV_RELEASE: + if (_chn[c].env >= ENV_RELEASE) { + _chn[c].env -= ENV_RELEASE; + } else { + _chn[c].env = 0; + } + } + } + + return BUFFER_SIZE; +} + +void SoundGenSarien::fillAudio(int16 *stream, uint len) { + uint32 p = 0; + + // current number of audio bytes in _sndBuffer + static uint32 data_available = 0; + // offset of start of audio bytes in _sndBuffer + static uint32 data_offset = 0; + + len <<= 2; + + debugC(5, kDebugLevelSound, "(%p, %d)", (void *)stream, len); + + while (len > data_available) { + memcpy((uint8 *)stream + p, (uint8*)_sndBuffer + data_offset, data_available); + p += data_available; + len -= data_available; + + playSound(); + data_available = mixSound() << 1; + data_offset = 0; + } + + memcpy((uint8 *)stream + p, (uint8*)_sndBuffer + data_offset, len); + data_offset += len; + data_available -= len; +} + +} // End of namespace Agi diff --git a/engines/agi/sound_sarien.h b/engines/agi/sound_sarien.h new file mode 100644 index 0000000000..54222ba624 --- /dev/null +++ b/engines/agi/sound_sarien.h @@ -0,0 +1,120 @@ +/* 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 AGI_SOUND_SARIEN_H +#define AGI_SOUND_SARIEN_H + +#include "sound/audiostream.h" + +namespace Agi { + +#define BUFFER_SIZE 410 + +#define WAVEFORM_SIZE 64 +#define ENV_ATTACK 10000 /**< envelope attack rate */ +#define ENV_DECAY 1000 /**< envelope decay rate */ +#define ENV_SUSTAIN 100 /**< envelope sustain level */ +#define ENV_RELEASE 7500 /**< envelope release rate */ +#define NUM_CHANNELS 7 /**< number of sound channels */ + +enum AgiSoundFlags { + AGI_SOUND_LOOP = 0x0001, + AGI_SOUND_ENVELOPE = 0x0002 +}; +enum AgiSoundEnv { + AGI_SOUND_ENV_ATTACK = 3, + AGI_SOUND_ENV_DECAY = 2, + AGI_SOUND_ENV_SUSTAIN = 1, + AGI_SOUND_ENV_RELEASE = 0 +}; + + +/** + * AGI engine sound channel structure. + */ +struct ChannelInfo { + AgiSoundEmuType type; + const uint8 *ptr; // Pointer to the AgiNote data + const int16 *ins; + int32 size; + uint32 phase; + uint32 flags; // ORs values from AgiSoundFlags + AgiSoundEnv adsr; + int32 timer; + uint32 end; + uint32 freq; + uint32 vol; + uint32 env; +}; + +class SoundGenSarien : public SoundGen, public Audio::AudioStream { +public: + SoundGenSarien(AgiEngine *vm, Audio::Mixer *pMixer); + ~SoundGenSarien(); + + void play(int resnum); + void stop(void); + + // AudioStream API + int readBuffer(int16 *buffer, const int numSamples); + + bool isStereo() const { + return false; + } + + bool endOfData() const { + return false; + } + + int getRate() const { + // FIXME: Ideally, we should use _sampleRate. + return 22050; + } + +private: + ChannelInfo _chn[NUM_CHANNELS]; + uint8 _env; + + int16 *_sndBuffer; + const int16 *_waveform; + + bool _useChorus; + + bool _playing; + int _playingSound; + +private: + void playSound(); + uint32 mixSound(); + void fillAudio(int16 *stream, uint len); + + void stopNote(int i); + void playNote(int i, int freq, int vol); + +}; + +} // End of namespace Agi + +#endif /* AGI_SOUND_SARIEN_H */ diff --git a/engines/agi/sprite.cpp b/engines/agi/sprite.cpp index 63ac880267..25118b69a6 100644 --- a/engines/agi/sprite.cpp +++ b/engines/agi/sprite.cpp @@ -241,6 +241,14 @@ void SpritesMgr::objsRestoreArea(Sprite *s) { q += xSize; pos0 += _WIDTH; } + + // WORKAROUND (see ScummVM bug #1945716) + // When set.view command is called, current code cannot detect this situation while updating + // Thus we force removal of the old sprite + if (s->v->viewReplaced) { + commitBlock(xPos, yPos, xPos + xSize, yPos + ySize); + s->v->viewReplaced = false; + } } @@ -332,6 +340,8 @@ void SpritesMgr::buildList(SpriteList &l, bool (*test)(VtEntry *, AgiEngine *)) } } + debugC(5, kDebugLevelSprites, "buildList() --> entries %d", i); + // now look for the smallest y value in the array and put that // sprite in the list for (j = 0; j < i; j++) { @@ -381,38 +391,20 @@ void SpritesMgr::freeList(SpriteList &l) { * Copy sprites from the pic buffer to the screen buffer, and check if * sprites of the given list have moved. */ -void SpritesMgr::commitSprites(SpriteList &l) { +void SpritesMgr::commitSprites(SpriteList &l, bool immediate) { SpriteList::iterator iter; for (iter = l.begin(); iter != l.end(); ++iter) { Sprite *s = *iter; - int x1, y1, x2, y2, w, h; + int x1, y1, x2, y2; - w = (s->v->celData->width > s->v->celData2->width) ? - s->v->celData->width : s->v->celData2->width; - - h = (s->v->celData->height > - s->v->celData2->height) ? s->v->celData-> - height : s->v->celData2->height; + x1 = MIN((int)MIN(s->v->xPos, s->v->xPos2), MIN(s->v->xPos + s->v->celData->width, s->v->xPos2 + s->v->celData2->width)); + x2 = MAX((int)MAX(s->v->xPos, s->v->xPos2), MAX(s->v->xPos + s->v->celData->width, s->v->xPos2 + s->v->celData2->width)); + y1 = MIN((int)MIN(s->v->yPos, s->v->yPos2), MIN(s->v->yPos - s->v->celData->height, s->v->yPos2 - s->v->celData2->height)); + y2 = MAX((int)MAX(s->v->yPos, s->v->yPos2), MAX(s->v->yPos - s->v->celData->height, s->v->yPos2 - s->v->celData2->height)); s->v->celData2 = s->v->celData; - if (s->v->xPos < s->v->xPos2) { - x1 = s->v->xPos; - x2 = s->v->xPos2 + w - 1; - } else { - x1 = s->v->xPos2; - x2 = s->v->xPos + w - 1; - } - - if (s->v->yPos < s->v->yPos2) { - y1 = s->v->yPos - h + 1; - y2 = s->v->yPos2; - } else { - y1 = s->v->yPos2 - h + 1; - y2 = s->v->yPos; - } - - commitBlock(x1, y1, x2, y2); + commitBlock(x1, y1, x2, y2, immediate); if (s->v->stepTimeCount != s->v->stepTime) continue; @@ -452,7 +444,7 @@ void SpritesMgr::blitSprites(SpriteList& l) { Sprite *s = *iter; objsSaveArea(s); - debugC(8, kDebugLevelSprites, "s->v->entry = %d (prio %d)", s->v->entry, s->v->priority); + debugC(8, kDebugLevelSprites, "blitSprites(): s->v->entry = %d (prio %d)", s->v->entry, s->v->priority); hidden = blitCel(s->xPos, s->yPos, s->v->priority, s->v->celData, s->v->viewData->agi256_2); if (s->v->entry == 0) { // if ego, update f1 @@ -466,11 +458,11 @@ void SpritesMgr::blitSprites(SpriteList& l) { */ void SpritesMgr::commitUpdSprites() { - commitSprites(_sprUpd); + commitSprites(_sprUpd, true); } void SpritesMgr::commitNonupdSprites() { - commitSprites(_sprNonupd); + commitSprites(_sprNonupd, true); } // check moves in both lists @@ -528,7 +520,7 @@ void SpritesMgr::eraseBoth() { * @see blit_both() */ void SpritesMgr::blitUpdSprites() { - debugC(7, kDebugLevelSprites, "blit updating"); + debugC(7, kDebugLevelSprites, "blitUpdSprites()"); buildUpdBlitlist(); blitSprites(_sprUpd); } @@ -542,7 +534,7 @@ void SpritesMgr::blitUpdSprites() { * @see blit_both() */ void SpritesMgr::blitNonupdSprites() { - debugC(7, kDebugLevelSprites, "blit non-updating"); + debugC(7, kDebugLevelSprites, "blitNonupdSprites()"); buildNonupdBlitlist(); blitSprites(_sprNonupd); } @@ -578,7 +570,7 @@ void SpritesMgr::addToPic(int view, int loop, int cel, int x, int y, int pri, in int x1, y1, x2, y2, y3; uint8 *p1, *p2; - debugC(3, kDebugLevelSprites, "v=%d, l=%d, c=%d, x=%d, y=%d, p=%d, m=%d", view, loop, cel, x, y, pri, mar); + debugC(3, kDebugLevelSprites, "addToPic(view=%d, loop=%d, cel=%d, x=%d, y=%d, pri=%d, mar=%d)", view, loop, cel, x, y, pri, mar); _vm->recordImageStackCall(ADD_VIEW, view, loop, cel, x, y, pri, mar); @@ -609,7 +601,7 @@ void SpritesMgr::addToPic(int view, int loop, int cel, int x, int y, int pri, in eraseBoth(); - debugC(4, kDebugLevelSprites, "blit_cel (%d, %d, %d, c)", x, y, pri); + debugC(4, kDebugLevelSprites, "blitCel(%d, %d, %d, c)", x, y, pri); blitCel(x1, y1, pri, c, _vm->_game.views[view].agi256_2); // If margin is 0, 1, 2, or 3, the base of the cel is @@ -659,8 +651,7 @@ void SpritesMgr::addToPic(int view, int loop, int cel, int x, int y, int pri, in blitBoth(); - debugC(4, kDebugLevelSprites, "commit_block (%d, %d, %d, %d)", x1, y1, x2, y2); - commitBlock(x1, y1, x2, y2); + commitBlock(x1, y1, x2, y2, true); } /** @@ -691,15 +682,15 @@ void SpritesMgr::showObj(int n) { objsSaveArea(&s); blitCel(x1, y1, 15, c, _vm->_game.views[n].agi256_2); - commitBlock(x1, y1, x2, y2); + commitBlock(x1, y1, x2, y2, true); _vm->messageBox(_vm->_game.views[n].descr); objsRestoreArea(&s); - commitBlock(x1, y1, x2, y2); + commitBlock(x1, y1, x2, y2, true); free(s.buffer); } -void SpritesMgr::commitBlock(int x1, int y1, int x2, int y2) { +void SpritesMgr::commitBlock(int x1, int y1, int x2, int y2, bool immediate) { int i, w, offset; uint8 *q; @@ -711,7 +702,7 @@ void SpritesMgr::commitBlock(int x1, int y1, int x2, int y2) { y1 = CLIP(y1, 0, _HEIGHT - 1); y2 = CLIP(y2, 0, _HEIGHT - 1); - debugC(7, kDebugLevelSprites, "%d, %d, %d, %d", x1, y1, x2, y2); + debugC(7, kDebugLevelSprites, "commitBlock(%d, %d, %d, %d)", x1, y1, x2, y2); w = x2 - x1 + 1; q = &_vm->_game.sbuf16c[x1 + _WIDTH * y1]; @@ -723,6 +714,9 @@ void SpritesMgr::commitBlock(int x1, int y1, int x2, int y2) { } _gfx->flushBlockA(x1, y1 + offset, x2, y2 + offset); + + if (immediate) + _gfx->doUpdate(); } SpritesMgr::SpritesMgr(AgiEngine *agi, GfxMgr *gfx) { diff --git a/engines/agi/sprite.h b/engines/agi/sprite.h index 7d6d7bb97e..57fd0dacf2 100644 --- a/engines/agi/sprite.h +++ b/engines/agi/sprite.h @@ -65,7 +65,7 @@ private: void buildUpdBlitlist(); void buildNonupdBlitlist(); void freeList(SpriteList &l); - void commitSprites(SpriteList &l); + void commitSprites(SpriteList &l, bool immediate = false); void eraseSprites(SpriteList &l); void blitSprites(SpriteList &l); static bool testUpdating(VtEntry *v, AgiEngine *); @@ -88,7 +88,7 @@ public: void commitBoth(); void addToPic(int, int, int, int, int, int, int); void showObj(int); - void commitBlock(int, int, int, int); + void commitBlock(int x1, int y1, int x2, int y2, bool immediate = false); }; } // End of namespace Agi diff --git a/engines/agi/text.cpp b/engines/agi/text.cpp index ee9aebf240..778da0a527 100644 --- a/engines/agi/text.cpp +++ b/engines/agi/text.cpp @@ -135,8 +135,8 @@ void AgiEngine::blitTextbox(const char *p, int y, int x, int len) { if (x == 0 && y == 0 && len == 0) x = y = -1; - if (len <= 0 || len >= 40) - len = 32; + if (len <= 0) + len = 30; xoff = x * CHAR_COLS; yoff = y * CHAR_LINES; @@ -214,6 +214,7 @@ void AgiEngine::printTextConsole(const char *msg, int x, int y, int len, int fg, x *= CHAR_COLS; y *= 10; + debugC(4, kDebugLevelText, "printTextConsole(): %s, %d, %d, %d, %d, %d", msg, x, y, len, fg, bg); printText2(1, msg, 0, x, y, len, fg, bg); } @@ -488,7 +489,7 @@ int AgiEngine::print(const char *p, int lin, int col, int len) { _game.keypress = 0; break; } - } while (_game.msgBoxTicks > 0); + } while (_game.msgBoxTicks > 0 && !(shouldQuit() || _restartGame)); setvar(vWindowReset, 0); @@ -655,11 +656,8 @@ void AgiEngine::writePrompt() { int l, fg, bg, pos; int promptLength = strlen(agiSprintf(_game.strings[0])); - if (!_game.inputEnabled || _game.inputMode != INPUT_NORMAL) { - clearPrompt(); - + if (!_game.inputEnabled || _game.inputMode != INPUT_NORMAL) return; - } l = _game.lineUserInput; fg = _game.colorFg; @@ -699,6 +697,8 @@ void AgiEngine::clearLines(int l1, int l2, int c) { // inc for endline so it matches the correct num // ie, from 22 to 24 is 3 lines, not 2 lines. + debugC(4, kDebugLevelText, "clearLines(%d, %d, %d)", l1, l2, c); + l1 *= CHAR_LINES; l2 *= CHAR_LINES; l2 += CHAR_LINES - 1; diff --git a/engines/agi/view.cpp b/engines/agi/view.cpp index fb417e86a9..45244bb292 100644 --- a/engines/agi/view.cpp +++ b/engines/agi/view.cpp @@ -294,37 +294,10 @@ void AgiEngine::setLoop(VtEntry *v, int n) { * @param n number of AGI view resource */ void AgiEngine::setView(VtEntry *v, int n) { - - uint16 viewFlags = 0; - - // When setting a view to the view table, if there's already another view set in that - // view table entry and it's still drawn, erase the existing view before setting the new one - // Fixes bug #1658643: AGI: SQ1 (2.2 DOS ENG) Graphic error, ego leaves behind copy - // Update: Apparently, this makes ego dissapear at times, e.g. when textboxes are shown - // Therefore, it's limited to view 118 in SQ1 (Roger climbing the ladder) - // Fixes bug #1715284: Roger sometimes disappears - if (v->viewData != NULL) { - if (v->currentView == 118 && v->flags & DRAWN && getGameID() == GID_SQ1) { - viewFlags = v->flags; // Store the flags for the view - _sprites->eraseUpdSprites(); - - if (v->flags & UPDATE) { - v->flags &= ~DRAWN; - } else { - _sprites->eraseNonupdSprites(); - v->flags &= ~DRAWN; - _sprites->blitNonupdSprites(); - } - _sprites->blitUpdSprites(); - - _sprites->commitBlock(v->xPos, v->yPos - v->ySize + 1, v->xPos + v->xSize - 1, v->yPos); - v->flags = viewFlags; // Restore the view's flags - } - } - v->viewData = &_game.views[n]; v->currentView = n; v->numLoops = v->viewData->numLoops; + v->viewReplaced = true; setLoop(v, v->currentLoop >= v->numLoops ? 0 : v->currentLoop); } @@ -338,6 +311,7 @@ void AgiEngine::startUpdate(VtEntry *v) { v->flags |= UPDATE; _sprites->blitBoth(); + _sprites->commitBoth(); } } @@ -351,6 +325,7 @@ void AgiEngine::stopUpdate(VtEntry *v) { v->flags &= ~UPDATE; _sprites->blitBoth(); + _sprites->commitBoth(); } } @@ -393,7 +368,7 @@ void AgiEngine::updateViewtable() { break; default: // for KQ4 - if (getVersion() == 0x3086) + if (getVersion() == 0x3086 || getGameID() == GID_KQ4) loop = loopTable4[v->direction]; break; } diff --git a/engines/agi/view.h b/engines/agi/view.h index f9017ec4ae..85f2d6eaf9 100644 --- a/engines/agi/view.h +++ b/engines/agi/view.h @@ -63,6 +63,7 @@ struct VtEntry { int16 xPos; int16 yPos; uint8 currentView; + bool viewReplaced; struct AgiView *viewData; uint8 currentLoop; uint8 numLoops; diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp index 6502866e8d..1b7802acb6 100644 --- a/engines/agos/agos.cpp +++ b/engines/agos/agos.cpp @@ -201,19 +201,19 @@ AGOSEngine::AGOSEngine(OSystem *syst) _scanFlag = false; _scriptVar2 = 0; - _runScriptReturn1 = 0; - _skipVgaWait = 0; - _noParentNotify = 0; - _beardLoaded = 0; - _litBoxFlag = 0; - _mortalFlag = 0; + _runScriptReturn1 = false; + _skipVgaWait = false; + _noParentNotify = false; + _beardLoaded = false; + _litBoxFlag = false; + _mortalFlag = false; _displayFlag = 0; - _syncFlag2 = 0; - _inCallBack = 0; - _cepeFlag = 0; - _fastMode = 0; + _syncFlag2 = false; + _inCallBack = false; + _cepeFlag = false; + _fastMode = false; - _backFlag = 0; + _backFlag = false; _debugMode = 0; _dumpScripts = false; @@ -556,10 +556,10 @@ Common::Error AGOSEngine::init() { (getPlatform() == Common::kPlatformPC)) { // Setup midi driver - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_ADLIB | MDT_MIDI); - _nativeMT32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_ADLIB | MDT_MIDI | (getGameType() == GType_SIMON1 ? MDT_PREFER_MT32 : MDT_PREFER_GM)); + _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); - _driver = MidiDriver::createMidi(midiDriver); + _driver = MidiDriver::createMidi(dev); if (_nativeMT32) { _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); @@ -630,9 +630,11 @@ Common::Error AGOSEngine::init() { if (ConfMan.hasKey("sfx_mute") && ConfMan.getBool("sfx_mute") == 1) { if (getGameId() == GID_SIMON1DOS) - _midi._enable_sfx ^= 1; - else - _sound->effectsPause(_effectsPaused ^= 1); + _midi._enable_sfx = !_midi._enable_sfx; + else { + _effectsPaused = !_effectsPaused; + _sound->effectsPause(_effectsPaused); + } } _copyProtection = ConfMan.getBool("copy_protection"); @@ -647,7 +649,7 @@ Common::Error AGOSEngine::init() { if (getGameType() == GType_SIMON1) { // English and German versions don't have full subtitles - if (_language == Common::EN_ANY || _language == Common::DE_DEU) + if (_language == Common::EN_ANY || _language == Common::DE_DEU) _subtitles = false; // Other versions require speech to be enabled else diff --git a/engines/agos/agos.h b/engines/agos/agos.h index ab1009e02a..b12bf09d62 100644 --- a/engines/agos/agos.h +++ b/engines/agos/agos.h @@ -393,7 +393,7 @@ protected: Common::Point _mouseOld; byte *_mouseData; - byte _animatePointer; + bool _animatePointer; byte _maxCursorWidth, _maxCursorHeight; byte _mouseAnim, _mouseAnimMax, _mouseCursor; byte _currentMouseAnim, _currentMouseCursor; diff --git a/engines/agos/cursor.cpp b/engines/agos/cursor.cpp index 109184e9c7..5ff2f014a6 100644 --- a/engines/agos/cursor.cpp +++ b/engines/agos/cursor.cpp @@ -459,7 +459,7 @@ void AGOSEngine_Simon1::handleMouseMoved() { _leftButtonDown = false; x = 1; } else { - if (_litBoxFlag == 0 && _needHitAreaRecalc == 0) + if (!_litBoxFlag && _needHitAreaRecalc == 0) goto get_out; } @@ -473,7 +473,7 @@ get_out: drawMousePointer(); _needHitAreaRecalc = 0; - _litBoxFlag = 0; + _litBoxFlag = false; } void AGOSEngine_PN::handleMouseMoved() { @@ -538,7 +538,7 @@ void AGOSEngine_PN::handleMouseMoved() { drawMousePointer(); _needHitAreaRecalc = 0; - _litBoxFlag = 0; + _litBoxFlag = false; } void AGOSEngine::handleMouseMoved() { @@ -610,7 +610,7 @@ void AGOSEngine::handleMouseMoved() { _oneClick = 0; x = 1; } else { - if (_litBoxFlag == 0 && _needHitAreaRecalc == 0) + if (!_litBoxFlag && _needHitAreaRecalc == 0) goto get_out; } @@ -622,7 +622,7 @@ get_out: drawMousePointer(); _needHitAreaRecalc = 0; - _litBoxFlag = 0; + _litBoxFlag = false; } void AGOSEngine::mouseOff() { @@ -706,10 +706,10 @@ void AGOSEngine_Feeble::drawMousePointer() { uint cursor; int image, offs; - if (_animatePointer != 0) { + if (_animatePointer) { if (getBitFlag(99)) { - _mouseToggle ^= 1; - if (_mouseToggle != 0) + _mouseToggle = !_mouseToggle; + if (_mouseToggle) _mouseAnim++; } else { _mouseAnim++; @@ -720,7 +720,7 @@ void AGOSEngine_Feeble::drawMousePointer() { cursor = _mouseCursor; - if (_animatePointer == 0 && getBitFlag(99)) { + if (!_animatePointer && getBitFlag(99)) { _mouseAnim = 1; cursor = 6; } else if (_mouseCursor != 5 && getBitFlag(72)) { diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp index 39974f9d53..646e63dacf 100644 --- a/engines/agos/detection.cpp +++ b/engines/agos/detection.cpp @@ -84,6 +84,11 @@ static const PlainGameDescriptor simonGames[] = { #include "agos/detection_tables.h" +static const char *directoryGlobs[] = { + "execute", // Used by Simon1 Acorn CD + 0 +}; + static const ADParams detectionParams = { // Pointer to ADGameDescription or its superset structure (const byte *)AGOS::gameDescriptions, @@ -102,7 +107,11 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NOLAUNCHLOAD + Common::GUIO_NOLAUNCHLOAD, + // Maximum directory depth + 2, + // List of directory globs + directoryGlobs }; using namespace AGOS; diff --git a/engines/agos/draw.cpp b/engines/agos/draw.cpp index 300ed4c52b..4d32b4521d 100644 --- a/engines/agos/draw.cpp +++ b/engines/agos/draw.cpp @@ -176,9 +176,9 @@ void AGOSEngine::animateSprites() { _windowNum = 4; - _backFlag = 1; + _backFlag = true; drawImage(&state); - _backFlag = 0; + _backFlag = false; _vgaSpriteChanged++; } @@ -451,14 +451,14 @@ void AGOSEngine::restoreBackGround() { state.paletteMod = 0; state.flags = kDFNonTrans; - _backFlag = 1; + _backFlag = true; drawImage(&state); if (getGameType() != GType_SIMON1 && getGameType() != GType_SIMON2) { animTable->srcPtr = 0; } } - _backFlag = 0; + _backFlag = false; if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { AnimTable *animTableTmp; diff --git a/engines/agos/event.cpp b/engines/agos/event.cpp index 3bbc0624aa..f3ec948f0f 100644 --- a/engines/agos/event.cpp +++ b/engines/agos/event.cpp @@ -479,7 +479,7 @@ void AGOSEngine::delay(uint amount) { _aboutDialog = new GUI::AboutDialog(); _aboutDialog->runModal(); } else if (event.kbd.keycode == Common::KEYCODE_f) { - _fastMode ^= 1; + _fastMode = !_fastMode; } else if (event.kbd.keycode == Common::KEYCODE_d) { _debugger->attach(); } else if (event.kbd.keycode == Common::KEYCODE_s) { @@ -566,7 +566,7 @@ void AGOSEngine_Feeble::timerProc() { _videoLockOut |= 2; if (!(_videoLockOut & 0x10)) { - _syncFlag2 ^= 1; + _syncFlag2 = !_syncFlag2; if (!_syncFlag2) { processVgaEvents(); } else { @@ -635,7 +635,7 @@ void AGOSEngine_PN::timerProc() { processVgaEvents(); processVgaEvents(); - _cepeFlag ^= 1; + _cepeFlag = !_cepeFlag; if (!_cepeFlag) processVgaEvents(); } @@ -661,7 +661,7 @@ void AGOSEngine::timerProc() { if (!(_videoLockOut & 0x10)) { processVgaEvents(); processVgaEvents(); - _cepeFlag ^= 1; + _cepeFlag = !_cepeFlag; if (!_cepeFlag) processVgaEvents(); } diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp index e2c634007c..82a4cb714b 100644 --- a/engines/agos/gfx.cpp +++ b/engines/agos/gfx.cpp @@ -730,7 +730,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) { state->paletteMod = 208; } - if (_backFlag == 1) { + if (_backFlag) { drawBackGroundImage(state); } else if (state->flags & kDFMasked) { drawMaskedImage(state); @@ -947,7 +947,7 @@ void AGOSEngine::drawImage(VC10_state *state) { if (getGameType() == GType_ELVIRA2 && getPlatform() == Common::kPlatformAtariST && yoffs > 133) state->palette = 208; - if (_backFlag == 1) { + if (_backFlag) { drawBackGroundImage(state); } else { drawVertImage(state); @@ -1351,7 +1351,7 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas if (getGameType() == GType_FF || getGameType() == GType_PP) { fillBackGroundFromBack(); - _syncFlag2 = 1; + _syncFlag2 = true; } else { _copyScnFlag = 2; _vgaSpriteChanged++; diff --git a/engines/agos/icons.cpp b/engines/agos/icons.cpp index fdc5d1707e..08a3d4e2f0 100644 --- a/engines/agos/icons.cpp +++ b/engines/agos/icons.cpp @@ -448,7 +448,7 @@ void AGOSEngine_Feeble::drawIconArray(uint num, Item *itemRef, int line, int cla setupIconHitArea(window, k++, xp, yp, itemRef); } else { /* - * Just remember the overflow has occured + * Just remember the overflow has occurred */ window->iconPtr->iconArray[icount].item = NULL; /* END MARKINGS */ _iOverflow = 1; diff --git a/engines/agos/input.cpp b/engines/agos/input.cpp index 35ed045675..5fc2a64416 100644 --- a/engines/agos/input.cpp +++ b/engines/agos/input.cpp @@ -99,7 +99,7 @@ void AGOSEngine::setup_cond_c_helper() { animMax = 9; } - _animatePointer = 0; + _animatePointer = false; _mouseCursor = cursor; _mouseAnimMax = animMax; _mouseAnim = 1; @@ -574,13 +574,13 @@ bool AGOSEngine::processSpecialKeys() { if (getGameType() == GType_FF || (getGameType() == GType_SIMON2 && (getFeatures() & GF_TALKIE)) || ((getFeatures() & GF_TALKIE) && _language != Common::EN_ANY && _language != Common::DE_DEU)) { if (_speech) - _subtitles ^= 1; + _subtitles = !_subtitles; } break; case 'v': if (getGameType() == GType_FF || (getGameType() == GType_SIMON2 && (getFeatures() & GF_TALKIE))) { if (_subtitles) - _speech ^= 1; + _speech = !_speech; } break; case '+': @@ -598,7 +598,7 @@ bool AGOSEngine::processSpecialKeys() { syncSoundSettings(); break; case 'm': - _musicPaused ^= 1; + _musicPaused = !_musicPaused; if (_midiEnabled) { _midi.pause(_musicPaused); } @@ -606,14 +606,16 @@ bool AGOSEngine::processSpecialKeys() { break; case 's': if (getGameId() == GID_SIMON1DOS) { - _midi._enable_sfx ^= 1; + _midi._enable_sfx = !_midi._enable_sfx; } else { - _sound->effectsPause(_effectsPaused ^= 1); + _effectsPaused = !_effectsPaused; + _sound->effectsPause(_effectsPaused); } break; case 'b': if (getGameType() == GType_SIMON2) { - _sound->ambientPause(_ambientPaused ^= 1); + _ambientPaused = !_ambientPaused; + _sound->ambientPause(_ambientPaused); } break; default: diff --git a/engines/agos/verb.cpp b/engines/agos/verb.cpp index a85c1627bf..b05bac1e57 100644 --- a/engines/agos/verb.cpp +++ b/engines/agos/verb.cpp @@ -207,7 +207,7 @@ static const char *const czech_verb_prep_names[] = { void AGOSEngine_Feeble::clearName() { stopAnimateSimon2(2, 6); _lastNameOn = NULL; - _animatePointer = 0; + _animatePointer = false; _mouseAnim = 1; return; } @@ -898,7 +898,7 @@ void AGOSEngine::displayName(HitArea *ha) { if (getBitFlag(99)) _animatePointer = ((ha->flags & kBFTextBox) == 0); else - _animatePointer = 1; + _animatePointer = true; if (!getBitFlag(73)) return; @@ -933,7 +933,7 @@ void AGOSEngine_Feeble::invertBox(HitArea *ha, bool state) { _mouseCursor = _oldMouseCursor; } else if (_mouseCursor != 18) { _oldMouseCursor = _mouseCursor; - _animatePointer = 0; + _animatePointer = false; _oldMouseAnimMax = _mouseAnimMax; _mouseAnimMax = 2; _mouseCursor = 18; diff --git a/engines/agos/vga_e2.cpp b/engines/agos/vga_e2.cpp index 1bbc7f4849..54ec45b967 100644 --- a/engines/agos/vga_e2.cpp +++ b/engines/agos/vga_e2.cpp @@ -265,7 +265,7 @@ void AGOSEngine::vc53_dissolveIn() { *dst &= color; *dst |= *src & 0xF; - _system->unlockScreen(); + _system->unlockScreen(); dissolveCount--; if (!dissolveCount) { @@ -319,7 +319,7 @@ void AGOSEngine::vc54_dissolveOut() { dst += xoffs; *dst = color; - _system->unlockScreen(); + _system->unlockScreen(); dissolveCount--; if (!dissolveCount) { @@ -388,7 +388,7 @@ void AGOSEngine::vc56_fullScreen() { src += 320; dst += screen->pitch; } - _system->unlockScreen(); + _system->unlockScreen(); fullFade(); } diff --git a/engines/agos/vga_s2.cpp b/engines/agos/vga_s2.cpp index 4eb739e974..db3a7c18f3 100644 --- a/engines/agos/vga_s2.cpp +++ b/engines/agos/vga_s2.cpp @@ -138,7 +138,7 @@ void AGOSEngine::vc69_playSeq() { // This is a "play track". The original // design stored the track to play if one was // already in progress, so that the next time a - // "fill MIDI stream" event occured, the MIDI + // "fill MIDI stream" event occurred, the MIDI // player would find the change and switch // tracks. We use a different architecture that // allows for an immediate response here, but diff --git a/engines/cine/detection.cpp b/engines/cine/detection.cpp index fcfa1f7f20..b92ad8a0a2 100644 --- a/engines/cine/detection.cpp +++ b/engines/cine/detection.cpp @@ -23,8 +23,6 @@ * */ - - #include "base/plugins.h" #include "engines/advancedDetector.h" @@ -62,494 +60,7 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = { {0, 0, Common::kPlatformUnknown} }; -namespace Cine { - -using Common::GUIO_NONE; - -static const CINEGameDescription gameDescriptions[] = { - { - { - "fw", - "", - AD_ENTRY1("part01", "61d003202d301c29dd399acfb1354310"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - // This is a CD version of Future Wars published by Sony. - // This version has a crypted AUTO00.PRC. - { - { - "fw", - "Sony CD version", - { - { "AUTO00.PRC", 0, "4fe1e7930b38e3c63f0f2474d471bf8f", -1}, - { "PART01", 0, "61d003202d301c29dd399acfb1354310", -1}, - { NULL, 0, NULL, 0} - }, - Common::EN_USA, - Common::kPlatformPC, - ADGF_CD, - GUIO_NONE - }, - GType_FW, - GF_CD | GF_CRYPTED_BOOT_PRC, - }, - - { - // This is the version included in the UK "Classic Collection" - { - "fw", - "", - AD_ENTRY1("part01", "91d7271155520eae6915a9dd2dac120c"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "f5e98fcca3fb5e7afa284c81c39d8b14"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - GF_ALT_FONT, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "570109f965c7f53984b98c83d86eb206"), - Common::ES_ESP, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - GF_ALT_FONT, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "5d1acb97abe9591f9008e00d07add95a"), - Common::FR_FRA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "57afd280b598b4180fda6689fbedc4b8"), - Common::EN_ANY, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { // Amiga "Interplay" labeled version - { - "fw", - "", - AD_ENTRY1("part01", "a17a5eb15200c63276d486a88263ccd0"), - Common::EN_USA, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "3a87a913e0e33963a48a7f822ca0eb0e"), - Common::DE_DEU, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - GF_ALT_FONT, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "5ad0007ccd5f7b3dd6b15ea7f281f9e1"), - Common::ES_ESP, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "460f2da8793bc581a2d4b6fc19ccb5ae"), - Common::FR_FRA, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "1c8e5207743172134409ac58860021af"), - Common::IT_ITA, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { - { - "fw", - "Demo", - { - { "demo", 0, "0f50767cd964e302d3af0ba2528df8c4", -1}, - { "demo.prc", 0, "d2ac3a743d288359c63644ea7071edae", -1}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformAmiga, - ADGF_DEMO, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "36050db13af57e462ca1adc4df99de4e"), - Common::EN_ANY, - Common::kPlatformAtariST, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "ef245573b7dab0d4825ceb98e37cef4d"), - Common::FR_FRA, - Common::kPlatformAtariST, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { - { - "os", - "256 colors", - AD_ENTRY1("procs00", "d6752e7d25924cb866b61eb7cb0c8b56"), - Common::EN_GRB, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - // This is a 16 color PC version (It came on three 720kB 3.5" disks). - // The protagonist is named John Glames in this version. - { - "os", - "", - AD_ENTRY1("procs1", "9629129b86979fa592c1787385bf3695"), - Common::EN_GRB, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "", - AD_ENTRY1("procs1", "d8c3a9d05a63e4cfa801826a7063a126"), - Common::EN_USA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "256 colors", - AD_ENTRY1("procs00", "862a75d76fb7fffec30e52be9ad1c474"), - Common::EN_USA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - GF_CD, - }, - - { - { - "os", - "", - AD_ENTRY1("procs1", "39b91ae35d1297ce0a76a1a803ca1593"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "", - AD_ENTRY1("procs1", "74c2dabd9d212525fca8875a5f6d8994"), - Common::ES_ESP, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "256 colors", - { - { "procs1", 0, "74c2dabd9d212525fca8875a5f6d8994", -1}, - { "sds1", 0, "75443ba39cdc95667e07d7118e5c151c", -1}, - { NULL, 0, NULL, 0} - }, - Common::ES_ESP, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - GF_CD, - }, - - { - { - "os", - "256 colors", - AD_ENTRY1("procs00", "f143567f08cfd1a9b1c9a41c89eadfef"), - Common::FR_FRA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "", - AD_ENTRY1("procs1", "da066e6b8dd93f2502c2a3755f08dc12"), - Common::IT_ITA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "", - AD_ENTRY1("procs0", "a9da5531ead0ebf9ad387fa588c0cbb0"), - Common::EN_GRB, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "alt", - AD_ENTRY1("procs0", "8a429ced2f4acff8a15ae125174042e8"), - Common::EN_GRB, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "", - AD_ENTRY1("procs0", "d5f27e33fc29c879f36f15b86ccfa58c"), - Common::EN_USA, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "", - AD_ENTRY1("procs0", "8b7dce249821d3a62b314399c4334347"), - Common::DE_DEU, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "", - AD_ENTRY1("procs0", "35fc295ddd0af9da932d256ba799a4b0"), - Common::ES_ESP, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "", - AD_ENTRY1("procs0", "d4ea4a97e01fa67ea066f9e785050ed2"), - Common::FR_FRA, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "Demo", - AD_ENTRY1("demo", "8d3a750d1c840b1b1071e42f9e6f6aa2"), - Common::EN_GRB, - Common::kPlatformAmiga, - ADGF_DEMO, - GUIO_NONE - }, - GType_OS, - GF_DEMO, - }, - - { - { - "os", - "", - AD_ENTRY1("procs0", "1501d5ae364b2814a33ed19347c3fcae"), - Common::EN_GRB, - Common::kPlatformAtariST, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "", - AD_ENTRY1("procs0", "2148d25de3219dd4a36580ca735d0afa"), - Common::FR_FRA, - Common::kPlatformAtariST, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { AD_TABLE_END_MARKER, 0, 0 } -}; - -} // End of namespace Cine +#include "cine/detection_tables.h" static const ADParams detectionParams = { // Pointer to ADGameDescription or its superset structure @@ -569,7 +80,11 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI + Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI, + // Maximum directory depth + 1, + // List of directory globs + 0 }; class CineMetaEngine : public AdvancedMetaEngine { diff --git a/engines/cine/detection_tables.h b/engines/cine/detection_tables.h new file mode 100644 index 0000000000..6e450ebc80 --- /dev/null +++ b/engines/cine/detection_tables.h @@ -0,0 +1,513 @@ +/* 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$ + * + */ + +namespace Cine { + +using Common::GUIO_NONE; + +static const CINEGameDescription gameDescriptions[] = { + { + { + "fw", + "", + AD_ENTRY1("part01", "61d003202d301c29dd399acfb1354310"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + // This is a CD version of Future Wars published by Sony. + // This version has a crypted AUTO00.PRC. + { + { + "fw", + "Sony CD version", + { + { "AUTO00.PRC", 0, "4fe1e7930b38e3c63f0f2474d471bf8f", -1}, + { "PART01", 0, "61d003202d301c29dd399acfb1354310", -1}, + { NULL, 0, NULL, 0} + }, + Common::EN_USA, + Common::kPlatformPC, + ADGF_CD, + GUIO_NONE + }, + GType_FW, + GF_CD | GF_CRYPTED_BOOT_PRC, + }, + + { + // This is the version included in the UK "Classic Collection" + { + "fw", + "", + AD_ENTRY1("part01", "91d7271155520eae6915a9dd2dac120c"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "f5e98fcca3fb5e7afa284c81c39d8b14"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + GF_ALT_FONT, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "570109f965c7f53984b98c83d86eb206"), + Common::ES_ESP, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + GF_ALT_FONT, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "5d1acb97abe9591f9008e00d07add95a"), + Common::FR_FRA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "57afd280b598b4180fda6689fbedc4b8"), + Common::EN_ANY, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { // Amiga "Interplay" labeled version + { + "fw", + "", + AD_ENTRY1("part01", "a17a5eb15200c63276d486a88263ccd0"), + Common::EN_USA, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "3a87a913e0e33963a48a7f822ca0eb0e"), + Common::DE_DEU, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + GF_ALT_FONT, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "5ad0007ccd5f7b3dd6b15ea7f281f9e1"), + Common::ES_ESP, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "460f2da8793bc581a2d4b6fc19ccb5ae"), + Common::FR_FRA, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "1c8e5207743172134409ac58860021af"), + Common::IT_ITA, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { + { + "fw", + "Demo", + { + { "demo", 0, "0f50767cd964e302d3af0ba2528df8c4", -1}, + { "demo.prc", 0, "d2ac3a743d288359c63644ea7071edae", -1}, + { NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformAmiga, + ADGF_DEMO, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "36050db13af57e462ca1adc4df99de4e"), + Common::EN_ANY, + Common::kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "ef245573b7dab0d4825ceb98e37cef4d"), + Common::FR_FRA, + Common::kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { + { + "os", + "256 colors", + AD_ENTRY1("procs00", "d6752e7d25924cb866b61eb7cb0c8b56"), + Common::EN_GRB, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + // This is a 16 color PC version (It came on three 720kB 3.5" disks). + // The protagonist is named John Glames in this version. + { + "os", + "", + AD_ENTRY1("procs1", "9629129b86979fa592c1787385bf3695"), + Common::EN_GRB, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "", + AD_ENTRY1("procs1", "d8c3a9d05a63e4cfa801826a7063a126"), + Common::EN_USA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "256 colors", + AD_ENTRY1("procs00", "862a75d76fb7fffec30e52be9ad1c474"), + Common::EN_USA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + GF_CD, + }, + + { + { + "os", + "", + AD_ENTRY1("procs1", "39b91ae35d1297ce0a76a1a803ca1593"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "", + AD_ENTRY1("procs1", "74c2dabd9d212525fca8875a5f6d8994"), + Common::ES_ESP, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "256 colors", + { + { "procs1", 0, "74c2dabd9d212525fca8875a5f6d8994", -1}, + { "sds1", 0, "75443ba39cdc95667e07d7118e5c151c", -1}, + { NULL, 0, NULL, 0} + }, + Common::ES_ESP, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + GF_CD, + }, + + { + { + "os", + "256 colors", + AD_ENTRY1("procs00", "f143567f08cfd1a9b1c9a41c89eadfef"), + Common::FR_FRA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "", + AD_ENTRY1("procs1", "da066e6b8dd93f2502c2a3755f08dc12"), + Common::IT_ITA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "", + AD_ENTRY1("procs0", "a9da5531ead0ebf9ad387fa588c0cbb0"), + Common::EN_GRB, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "alt", + AD_ENTRY1("procs0", "8a429ced2f4acff8a15ae125174042e8"), + Common::EN_GRB, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "", + AD_ENTRY1("procs0", "d5f27e33fc29c879f36f15b86ccfa58c"), + Common::EN_USA, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "", + AD_ENTRY1("procs0", "8b7dce249821d3a62b314399c4334347"), + Common::DE_DEU, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "", + AD_ENTRY1("procs0", "35fc295ddd0af9da932d256ba799a4b0"), + Common::ES_ESP, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "", + AD_ENTRY1("procs0", "d4ea4a97e01fa67ea066f9e785050ed2"), + Common::FR_FRA, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "Demo", + AD_ENTRY1("demo", "8d3a750d1c840b1b1071e42f9e6f6aa2"), + Common::EN_GRB, + Common::kPlatformAmiga, + ADGF_DEMO, + GUIO_NONE + }, + GType_OS, + GF_DEMO, + }, + + { + { + "os", + "", + AD_ENTRY1("procs0", "1501d5ae364b2814a33ed19347c3fcae"), + Common::EN_GRB, + Common::kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "", + AD_ENTRY1("procs0", "2148d25de3219dd4a36580ca735d0afa"), + Common::FR_FRA, + Common::kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { AD_TABLE_END_MARKER, 0, 0 } +}; + +} // End of namespace Cine diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp index a4220e6e35..1f747c5a01 100644 --- a/engines/cine/gfx.cpp +++ b/engines/cine/gfx.cpp @@ -772,7 +772,7 @@ const char *FWRenderer::getBgName(uint idx) const { * Restore active and backup palette from save * @param fHandle Savefile open for reading */ -void FWRenderer::restorePalette(Common::SeekableReadStream &fHandle) { +void FWRenderer::restorePalette(Common::SeekableReadStream &fHandle, int version) { byte buf[kLowPalNumBytes]; // Load the active 16 color palette from file @@ -819,9 +819,8 @@ void FWRenderer::savePalette(Common::OutSaveFile &fHandle) { void OSRenderer::savePalette(Common::OutSaveFile &fHandle) { byte buf[kHighPalNumBytes]; - // Make sure the active palette has the correct format and color count - assert(_activePal.colorFormat() == kHighPalFormat); - assert(_activePal.colorCount() == kHighPalNumColors); + // We can have 16 color palette in many cases + fHandle.writeUint16LE(_activePal.colorCount()); // Write the active 256 color palette. _activePal.save(buf, sizeof(buf), CINE_LITTLE_ENDIAN); @@ -836,12 +835,18 @@ void OSRenderer::savePalette(Common::OutSaveFile &fHandle) { * Restore active and backup palette from save * @param fHandle Savefile open for reading */ -void OSRenderer::restorePalette(Common::SeekableReadStream &fHandle) { +void OSRenderer::restorePalette(Common::SeekableReadStream &fHandle, int version) { byte buf[kHighPalNumBytes]; + uint colorCount = (version > 0) ? fHandle.readUint16LE() : kHighPalNumBytes; - // Load the active 256 color palette from file fHandle.read(buf, kHighPalNumBytes); - _activePal.load(buf, sizeof(buf), kHighPalFormat, kHighPalNumColors, CINE_LITTLE_ENDIAN); + + if (colorCount == kHighPalNumBytes) { + // Load the active 256 color palette from file + _activePal.load(buf, sizeof(buf), kHighPalFormat, kHighPalNumColors, CINE_LITTLE_ENDIAN); + } else { + _activePal.load(buf, sizeof(buf), kLowPalFormat, kLowPalNumColors, CINE_LITTLE_ENDIAN); + } // Jump over the backup 256 color palette. // FIXME: Load the backup 256 color palette and use it properly. diff --git a/engines/cine/gfx.h b/engines/cine/gfx.h index 56ba6885f4..da7e3dd572 100644 --- a/engines/cine/gfx.h +++ b/engines/cine/gfx.h @@ -197,7 +197,7 @@ public: virtual void refreshPalette(); virtual void reloadPalette(); - virtual void restorePalette(Common::SeekableReadStream &fHandle); + virtual void restorePalette(Common::SeekableReadStream &fHandle, int version); virtual void savePalette(Common::OutSaveFile &fHandle); virtual void rotatePalette(int a, int b, int c); virtual void transformPalette(int first, int last, int r, int g, int b); @@ -257,7 +257,7 @@ public: const char *getBgName(uint idx = 0) const; void reloadPalette(); - void restorePalette(Common::SeekableReadStream &fHandle); + void restorePalette(Common::SeekableReadStream &fHandle, int version); void savePalette(Common::OutSaveFile &fHandle); void transformPalette(int first, int last, int r, int g, int b); diff --git a/engines/cine/saveload.cpp b/engines/cine/saveload.cpp index c76bed3f8e..b5adebcd0b 100644 --- a/engines/cine/saveload.cpp +++ b/engines/cine/saveload.cpp @@ -566,7 +566,7 @@ bool CineEngine::loadTempSaveOS(Common::SeekableReadStream &in) { } loadObjectTable(in); - renderer->restorePalette(in); + renderer->restorePalette(in, hdr.version); globalVars.load(in, NUM_MAX_VAR); loadZoneData(in); loadCommandVariables(in); @@ -698,7 +698,7 @@ bool CineEngine::loadPlainSaveFW(Common::SeekableReadStream &in, CineSaveGameFor loadObjectTable(in); // At 0x2043 (i.e. 0x005F + 2 * 2 + 255 * 32): - renderer->restorePalette(in); + renderer->restorePalette(in, 0); // At 0x2083 (i.e. 0x2043 + 16 * 2 * 2): globalVars.load(in, NUM_MAX_VAR); diff --git a/engines/cine/saveload.h b/engines/cine/saveload.h index 65f24f838d..a6e0e3f1ab 100644 --- a/engines/cine/saveload.h +++ b/engines/cine/saveload.h @@ -74,7 +74,7 @@ enum CineSaveGameFormat { static const uint32 TEMP_OS_FORMAT_ID = MKID_BE('TEMP'); /** The current version number of Operation Stealth's savegame format. */ -static const uint32 CURRENT_OS_SAVE_VER = 0; +static const uint32 CURRENT_OS_SAVE_VER = 1; /** Chunk header used by the temporary Operation Stealth savegame format. */ struct ChunkHeader { diff --git a/engines/cruise/decompiler.cpp b/engines/cruise/decompiler.cpp index ba4ade56a7..31d9dcef9b 100644 --- a/engines/cruise/decompiler.cpp +++ b/engines/cruise/decompiler.cpp @@ -760,8 +760,6 @@ int decompFunction() { char *var1; char *objIdxStr; char *ovlStr; - char varName[256]; - int i; var1 = popDecomp(); objIdxStr = popDecomp(); diff --git a/engines/cruise/detection.cpp b/engines/cruise/detection.cpp index e1f12b734e..e43fadf598 100644 --- a/engines/cruise/detection.cpp +++ b/engines/cruise/detection.cpp @@ -237,7 +237,11 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI + Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI, + // Maximum directory depth + 1, + // List of directory globs + 0 }; class CruiseMetaEngine : public AdvancedMetaEngine { diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp index 954bc81470..2397a474c6 100644 --- a/engines/dialogs.cpp +++ b/engines/dialogs.cpp @@ -28,6 +28,7 @@ #include "common/savefile.h" #include "common/system.h" #include "common/events.h" +#include "common/translation.h" #include "graphics/scaler.h" @@ -85,37 +86,37 @@ MainMenuDialog::MainMenuDialog(Engine *engine) StaticTextWidget *version = new StaticTextWidget(this, "GlobalMenu.Version", gScummVMVersionDate); version->setAlign(Graphics::kTextAlignCenter); - new GUI::ButtonWidget(this, "GlobalMenu.Resume", "Resume", kPlayCmd, 'P'); + new GUI::ButtonWidget(this, "GlobalMenu.Resume", _("~R~esume"), 0, kPlayCmd, 'P'); - _loadButton = new GUI::ButtonWidget(this, "GlobalMenu.Load", "Load", kLoadCmd, 'L'); + _loadButton = new GUI::ButtonWidget(this, "GlobalMenu.Load", _("~L~oad"), 0, kLoadCmd); // TODO: setEnabled -> setVisible _loadButton->setEnabled(_engine->hasFeature(Engine::kSupportsLoadingDuringRuntime)); - _saveButton = new GUI::ButtonWidget(this, "GlobalMenu.Save", "Save", kSaveCmd, 'S'); + _saveButton = new GUI::ButtonWidget(this, "GlobalMenu.Save", _("~S~ave"), 0, kSaveCmd); // TODO: setEnabled -> setVisible _saveButton->setEnabled(_engine->hasFeature(Engine::kSupportsSavingDuringRuntime)); - new GUI::ButtonWidget(this, "GlobalMenu.Options", "Options", kOptionsCmd, 'O'); + new GUI::ButtonWidget(this, "GlobalMenu.Options", _("~O~ptions"), 0, kOptionsCmd); // 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 = new GUI::ButtonWidget(this, "GlobalMenu.Help", _("~H~elp"), 0, kHelpCmd); _helpButton->setEnabled(false); - new GUI::ButtonWidget(this, "GlobalMenu.About", "About", kAboutCmd, 'A'); + new GUI::ButtonWidget(this, "GlobalMenu.About", _("~A~bout"), 0, kAboutCmd); - _rtlButton = new GUI::ButtonWidget(this, "GlobalMenu.RTL", "Return to Launcher", kRTLCmd, 'R'); + _rtlButton = new GUI::ButtonWidget(this, "GlobalMenu.RTL", _("~R~eturn to Launcher"), 0, kRTLCmd); _rtlButton->setEnabled(_engine->hasFeature(Engine::kSupportsRTL)); - new GUI::ButtonWidget(this, "GlobalMenu.Quit", "Quit", kQuitCmd, 'Q'); + new GUI::ButtonWidget(this, "GlobalMenu.Quit", _("~Q~uit"), 0, kQuitCmd); _aboutDialog = new GUI::AboutDialog(); _optionsDialog = new ConfigDialog(_engine->hasFeature(Engine::kSupportsSubtitleOptions)); - _loadDialog = new GUI::SaveLoadChooser("Load game:", "Load"); + _loadDialog = new GUI::SaveLoadChooser(_("Load game:"), _("Load")); _loadDialog->setSaveMode(false); - _saveDialog = new GUI::SaveLoadChooser("Save game:", "Save"); + _saveDialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save")); _saveDialog->setSaveMode(true); } @@ -297,11 +298,11 @@ ConfigDialog::ConfigDialog(bool subtitleControls) // Add the buttons // - new GUI::ButtonWidget(this, "GlobalConfig.Ok", "OK", GUI::kOKCmd, 'O'); - new GUI::ButtonWidget(this, "GlobalConfig.Cancel", "Cancel", GUI::kCloseCmd, 'C'); + new GUI::ButtonWidget(this, "GlobalConfig.Ok", _("~O~K"), 0, GUI::kOKCmd); + new GUI::ButtonWidget(this, "GlobalConfig.Cancel", _("~C~ancel"), 0, GUI::kCloseCmd); #ifdef SMALL_SCREEN_DEVICE - new GUI::ButtonWidget(this, "GlobalConfig.Keys", "Keys", kKeysCmd, 'K'); + new GUI::ButtonWidget(this, "GlobalConfig.Keys", _("~K~eys"), 0, kKeysCmd); _keysDialog = NULL; #endif } diff --git a/engines/draci/animation.cpp b/engines/draci/animation.cpp index e46582487c..2bedbe1801 100644 --- a/engines/draci/animation.cpp +++ b/engines/draci/animation.cpp @@ -166,10 +166,10 @@ void Animation::drawFrame(Surface *surface) { const SoundSample *sample = _samples[_currentFrame]; if (_hasChangedFrame && sample) { + uint duration = _vm->_sound->playSound(sample, Audio::Mixer::kMaxChannelVolume, false); debugC(3, kDraciSoundDebugLevel, - "Playing sample on animation %d, frame %d: %d+%d at %dHz", - _id, _currentFrame, sample->_offset, sample->_length, sample->_frequency); - _vm->_sound->playSound(sample, Audio::Mixer::kMaxChannelVolume, false); + "Playing sample on animation %d, frame %d: %d+%d at %dHz: %dms", + _id, _currentFrame, sample->_offset, sample->_length, sample->_frequency, duration); } _hasChangedFrame = false; } diff --git a/engines/draci/barchive.cpp b/engines/draci/barchive.cpp index 2ed2a9b591..8f9e836ba3 100644 --- a/engines/draci/barchive.cpp +++ b/engines/draci/barchive.cpp @@ -283,8 +283,7 @@ BAFile *BArchive::loadFileBAR(uint i) { tmp ^= _files[i]._data[j]; } - debugC(3, kDraciArchiverDebugLevel, "Cached file %d from archive %s", - i, _path.c_str()); + debugC(2, kDraciArchiverDebugLevel, "Read %d bytes", _files[i]._length); assert(tmp == _files[i]._crc && "CRC checksum mismatch"); return _files + i; @@ -385,7 +384,7 @@ const BAFile *BArchive::getFile(uint i) { // Check if file has already been opened and return that if (_files[i]._data) { - debugC(2, kDraciArchiverDebugLevel, "Success"); + debugC(2, kDraciArchiverDebugLevel, "Cached"); return _files + i; } diff --git a/engines/draci/detection.cpp b/engines/draci/detection.cpp index c3204fc656..e1025e698a 100644 --- a/engines/draci/detection.cpp +++ b/engines/draci/detection.cpp @@ -94,7 +94,11 @@ const ADParams detectionParams = { // Flags 0, // Global GUI options - Common::GUIO_NONE + Common::GUIO_NONE, + // Maximum directory depth + 1, + // List of directory globs + 0 }; class DraciMetaEngine : public AdvancedMetaEngine { diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp index cbf878279b..cd3920b30d 100644 --- a/engines/draci/draci.cpp +++ b/engines/draci/draci.cpp @@ -71,7 +71,7 @@ const char *dubbingPath = "CD.SAM"; const char *musicPathMask = "HUDBA%d.MID"; const uint kSoundsFrequency = 13000; -const uint kDubbingFrequency = 22000; +const uint kDubbingFrequency = 22050; DraciEngine::DraciEngine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst) { @@ -105,6 +105,39 @@ bool DraciEngine::hasFeature(EngineFeature f) const { (f == kSupportsSavingDuringRuntime); } +static SoundArchive* openAnyPossibleDubbing() { + debugC(1, kDraciGeneralDebugLevel, "Trying to find original dubbing"); + LegacySoundArchive *legacy = new LegacySoundArchive(dubbingPath, kDubbingFrequency); + if (legacy->isOpen() && legacy->size()) { + debugC(1, kDraciGeneralDebugLevel, "Found original dubbing"); + return legacy; + } + delete legacy; + + // The original uncompressed dubbing cannot be found. Try to open the + // newer compressed version. + debugC(1, kDraciGeneralDebugLevel, "Trying to find compressed dubbing"); + ZipSoundArchive *zip = new ZipSoundArchive(); + + zip->openArchive("dub-raw.zzz", "buf", RAW80, kDubbingFrequency); + if (zip->isOpen() && zip->size()) return zip; +#ifdef USE_FLAC + zip->openArchive("dub-flac.zzz", "flac", FLAC); + if (zip->isOpen() && zip->size()) return zip; +#endif +#ifdef USE_VORBIS + zip->openArchive("dub-ogg.zzz", "ogg", OGG); + if (zip->isOpen() && zip->size()) return zip; +#endif +#ifdef USE_MAD + zip->openArchive("dub-mp3.zzz", "mp3", MP3); + if (zip->isOpen() && zip->size()) return zip; +#endif + + // Return an empty (but initialized) archive anyway. + return zip; +} + int DraciEngine::init() { // Initialize graphics using following: initGraphics(kScreenWidth, kScreenHeight, false); @@ -123,15 +156,15 @@ int DraciEngine::init() { _itemImagesArchive = new BArchive(itemImagesPath); _stringsArchive = new BArchive(stringsPath); - _soundsArchive = new SoundArchive(soundsPath, kSoundsFrequency); - _dubbingArchive = new SoundArchive(dubbingPath, kDubbingFrequency); + _soundsArchive = new LegacySoundArchive(soundsPath, kSoundsFrequency); + _dubbingArchive = openAnyPossibleDubbing(); _sound = new Sound(_mixer); - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); - //bool adlib = (midiDriver == MD_ADLIB); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); + bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); + //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB); - _midiDriver = MidiDriver::createMidi(midiDriver); + _midiDriver = MidiDriver::createMidi(dev); if (native_mt32) _midiDriver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); @@ -253,19 +286,20 @@ void DraciEngine::handleEvents() { if (escRoom >= 0) { // Schedule room change - // TODO: gate 0 (always present) is not - // always best for returning from the - // map, e.g. in the starting location. - // also, after loading the game, we - // shouldn't run any gate program, but - // rather restore the state of all - // objects. + // TODO: gate 0 (always present) is not always best for + // returning from the map, e.g. in the starting location. + // also, after loading the game, we shouldn't run any gate + // program, but rather restore the state of all objects. _game->scheduleEnteringRoomUsingGate(escRoom, 0); - // Immediately cancel any running animation or dubbing. + // Immediately cancel any running animation or dubbing and + // end any currently running GPL programs. In the intro it + // works as intended---skipping the rest of it. + // + // In the map, this causes that animation on newly + // discovered locations will be re-run next time and + // cut-scenes won't be played. _game->setExitLoop(true); - - // End any currently running GPL programs _script->endCurrentProgram(true); } break; @@ -301,6 +335,16 @@ void DraciEngine::handleEvents() { openMainMenuDialog(); } break; + case Common::KEYCODE_COMMA: + case Common::KEYCODE_PERIOD: + case Common::KEYCODE_SLASH: + if ((_game->getLoopStatus() == kStatusOrdinary || + _game->getLoopStatus() == kStatusInventory) && + _game->getLoopSubstatus() == kOuterLoop && + _game->getRoomNum() != _game->getMapRoom()) { + _game->inventorySwitch(event.kbd.keycode); + } + break; default: break; } diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp index 0e4b3386ec..8f3ad12cfd 100644 --- a/engines/draci/game.cpp +++ b/engines/draci/game.cpp @@ -23,6 +23,7 @@ * */ +#include "common/keyboard.h" #include "common/serializer.h" #include "common/stream.h" #include "common/system.h" @@ -174,8 +175,20 @@ void Game::start() { // Call the outer loop doing all the hard job. loop(kOuterLoop, false); - } + // Fade out the palette after leaving the location. + fadePalette(true); + + if (!isReloaded()) { + // We are changing location. Run the hero's LOOK + // program to trigger a possible cut-scene. This is + // the behavior of the original game player, whose + // intention was to run the cut sequences after the + // certain location change. + const GameObject *dragon = getObject(kDragonObject); + _vm->_script->run(dragon->_program, dragon->_look); + } + } } void Game::init() { @@ -193,7 +206,8 @@ void Game::init() { _animUnderCursor = NULL; _currentItem = _itemUnderCursor = NULL; - + _previousItemPosition = -1; + _vm->_mouse->setCursorType(kHighlightedCursor); // anything different from kNormalCursor _objUnderCursor = NULL; @@ -263,8 +277,8 @@ void Game::handleOrdinaryLoop(int x, int y) { if (_vm->_mouse->lButtonPressed()) { _vm->_mouse->lButtonSet(false); - if (_currentItem) { - putItem(_currentItem, 0); + if (getCurrentItem()) { + putItem(getCurrentItem(), getPreviousItemPosition()); updateOrdinaryCursor(); } else { if (_objUnderCursor) { @@ -318,6 +332,16 @@ void Game::handleOrdinaryLoop(int x, int y) { } } +int Game::inventoryPositionFromMouse() const { + const int column = CLIP(scummvm_lround( + (_vm->_mouse->getPosX() - kInventoryX + kInventoryItemWidth / 2.) / + kInventoryItemWidth) - 1, 0L, (long) kInventoryColumns - 1); + const int line = CLIP(scummvm_lround( + (_vm->_mouse->getPosY() - kInventoryY + kInventoryItemHeight / 2.) / + kInventoryItemHeight) - 1, 0L, (long) kInventoryLines - 1); + return line * kInventoryColumns + column; +} + void Game::handleInventoryLoop() { if (_loopSubstatus != kOuterLoop) { return; @@ -344,19 +368,12 @@ void Game::handleInventoryLoop() { // If there is an inventory item under the cursor and we aren't // holding any item, run its look GPL program - if (_itemUnderCursor && !_currentItem) { + if (_itemUnderCursor && !getCurrentItem()) { _vm->_script->runWrapper(_itemUnderCursor->_program, _itemUnderCursor->_look, true, false); // Otherwise, if we are holding an item, try to place it inside the // inventory - } else if (_currentItem) { - const int column = CLIP(scummvm_lround( - (_vm->_mouse->getPosX() - kInventoryX + kInventoryItemWidth / 2.) / - kInventoryItemWidth) - 1, 0L, (long) kInventoryColumns - 1); - const int line = CLIP(scummvm_lround( - (_vm->_mouse->getPosY() - kInventoryY + kInventoryItemHeight / 2.) / - kInventoryItemHeight) - 1, 0L, (long) kInventoryLines - 1); - const int index = line * kInventoryColumns + column; - putItem(_currentItem, index); + } else if (getCurrentItem()) { + putItem(getCurrentItem(), inventoryPositionFromMouse()); updateInventoryCursor(); } } else if (_vm->_mouse->rButtonPressed()) { @@ -372,8 +389,9 @@ void Game::handleInventoryLoop() { // The first is that there is no item in our hands. // In that case, just take the inventory item from the inventory. - if (!_currentItem) { - _currentItem = _itemUnderCursor; + if (!getCurrentItem()) { + setCurrentItem(_itemUnderCursor); + setPreviousItemPosition(inventoryPositionFromMouse()); removeItem(_itemUnderCursor); // The second is that there *is* an item in our hands. @@ -413,6 +431,22 @@ void Game::handleDialogueLoop() { } } +void Game::fadePalette(bool fading_out) { + const byte *startPal = NULL; + const byte *endPal = _currentRoom._palette >= 0 + ? _vm->_paletteArchive->getFile(_currentRoom._palette)->_data + : NULL; + if (fading_out) { + startPal = endPal; + endPal = NULL; + } + for (int i = 1; i <= kBlackFadingIterations; ++i) { + _vm->_system->delayMillis(kBlackFadingTimeUnit); + _vm->_screen->interpolatePalettes(startPal, endPal, 0, kNumColours, i, kBlackFadingIterations); + _vm->_screen->copyToScreen(); + } +} + void Game::advanceAnimationsAndTestLoopExit() { // Fade the palette if requested if (_fadePhase > 0 && (_vm->_system->getMillis() - _fadeTick) >= kFadingTimeUnit) { @@ -470,7 +504,7 @@ void Game::advanceAnimationsAndTestLoopExit() { // callbacks) and redraw screen _vm->_anims->drawScene(_vm->_screen->getSurface()); _vm->_screen->copyToScreen(); - _vm->_system->delayMillis(20); + _vm->_system->delayMillis(kTimeUnit); // If the hero has arrived at his destination, after even the last // phase was correctly animated, run the callback. @@ -614,10 +648,10 @@ void Game::updateOrdinaryCursor() { // If there is no game object under the cursor, try using the room itself if (!_objUnderCursor) { if (_vm->_script->testExpression(_currentRoom._program, _currentRoom._canUse)) { - if (!_currentItem) { + if (!getCurrentItem()) { _vm->_mouse->setCursorType(kHighlightedCursor); } else { - _vm->_mouse->loadItemCursor(_currentItem, true); + _vm->_mouse->loadItemCursor(getCurrentItem(), true); } mouseChanged = true; } @@ -628,10 +662,10 @@ void Game::updateOrdinaryCursor() { // update the cursor image (highlight it). if (_objUnderCursor->_walkDir == 0) { if (_vm->_script->testExpression(_objUnderCursor->_program, _objUnderCursor->_canUse)) { - if (!_currentItem) { + if (!getCurrentItem()) { _vm->_mouse->setCursorType(kHighlightedCursor); } else { - _vm->_mouse->loadItemCursor(_currentItem, true); + _vm->_mouse->loadItemCursor(getCurrentItem(), true); } mouseChanged = true; } @@ -645,10 +679,10 @@ void Game::updateOrdinaryCursor() { // Load the appropriate cursor (item image if an item is held or ordinary cursor // if not) if (!mouseChanged) { - if (!_currentItem) { + if (!getCurrentItem()) { _vm->_mouse->setCursorType(kNormalCursor); } else { - _vm->_mouse->loadItemCursor(_currentItem, false); + _vm->_mouse->loadItemCursor(getCurrentItem(), false); } } } @@ -659,19 +693,19 @@ void Game::updateInventoryCursor() { if (_itemUnderCursor) { if (_vm->_script->testExpression(_itemUnderCursor->_program, _itemUnderCursor->_canUse)) { - if (!_currentItem) { + if (!getCurrentItem()) { _vm->_mouse->setCursorType(kHighlightedCursor); } else { - _vm->_mouse->loadItemCursor(_currentItem, true); + _vm->_mouse->loadItemCursor(getCurrentItem(), true); } mouseChanged = true; } } if (!mouseChanged) { - if (!_currentItem) { + if (!getCurrentItem()) { _vm->_mouse->setCursorType(kNormalCursor); } else { - _vm->_mouse->loadItemCursor(_currentItem, false); + _vm->_mouse->loadItemCursor(getCurrentItem(), false); } } } @@ -723,6 +757,8 @@ const GameObject *Game::getObjectWithAnimation(const Animation *anim) const { } void Game::removeItem(GameItem *item) { + if (!item) + return; for (uint i = 0; i < kInventorySlots; ++i) { if (_inventory[i] == item) { _inventory[i] = NULL; @@ -744,7 +780,7 @@ void Game::loadItemAnimation(GameItem *item) { void Game::putItem(GameItem *item, int position) { // Empty our hands - _currentItem = NULL; + setCurrentItem(NULL); if (!item) return; @@ -758,6 +794,7 @@ void Game::putItem(GameItem *item, int position) { break; } } + setPreviousItemPosition(position); const int line = position / kInventoryColumns + 1; const int column = position % kInventoryColumns + 1; @@ -845,6 +882,55 @@ void Game::inventoryReload() { for (uint i = 0; i < kInventorySlots; ++i) { putItem(_inventory[i], i); } + setPreviousItemPosition(0); +} + +void Game::inventorySwitch(int keycode) { + switch (keycode) { + case Common::KEYCODE_SLASH: + // Switch between holding an item and the ordinary mouse cursor. + if (!getCurrentItem()) { + if (getPreviousItemPosition() >= 0) { + GameItem* last_item = _inventory[getPreviousItemPosition()]; + setCurrentItem(last_item); + removeItem(last_item); + } + } else { + putItem(getCurrentItem(), getPreviousItemPosition()); + } + break; + case Common::KEYCODE_COMMA: + case Common::KEYCODE_PERIOD: + // Iterate between the items in the inventory. + if (getCurrentItem()) { + assert(getPreviousItemPosition() >= 0); + int direction = keycode == Common::KEYCODE_PERIOD ? +1 : -1; + // Find the next available item. + int pos = getPreviousItemPosition() + direction; + while (true) { + if (pos < 0) + pos += kInventorySlots; + else if (pos >= kInventorySlots) + pos -= kInventorySlots; + if (pos == getPreviousItemPosition() || _inventory[pos]) { + break; + } + pos += direction; + } + // Swap it with the current item. + putItem(getCurrentItem(), getPreviousItemPosition()); + GameItem* new_item = _inventory[pos]; + setCurrentItem(new_item); + setPreviousItemPosition(pos); + removeItem(new_item); + } + break; + } + if (getLoopStatus() == kStatusOrdinary) { + updateOrdinaryCursor(); + } else { + updateInventoryCursor(); + } } void Game::dialogueMenu(int dialogueID) { @@ -1297,10 +1383,11 @@ void Game::enterNewRoom() { loadRoomObjects(); loadOverlays(); - // Set room palette - const BAFile *f; - f = _vm->_paletteArchive->getFile(_currentRoom._palette); - _vm->_screen->setPalette(f->_data, 0, kNumColours); + // Draw the scene with the black palette and slowly fade into the right palette. + _vm->_screen->setPalette(NULL, 0, kNumColours); + _vm->_anims->drawScene(_vm->_screen->getSurface()); + _vm->_screen->copyToScreen(); + fadePalette(false); // Run the program for the gate the dragon came through debugC(6, kDraciLogicDebugLevel, "Running program for gate %d", _newGate); diff --git a/engines/draci/game.h b/engines/draci/game.h index 3d02489da7..21baaed5cc 100644 --- a/engines/draci/game.h +++ b/engines/draci/game.h @@ -65,9 +65,16 @@ enum SpeechConstants { kStandardSpeed = 60 }; -// One fading phase is 50ms. enum FadeConstants { - kFadingTimeUnit = 50 + // One fading phase called from the game scripts is 50ms. + kFadingTimeUnit = 50, + // Fading in/out when entering/leaving a location takes 15 iterations of (at least) 7ms each. + kBlackFadingIterations = 15, + kBlackFadingTimeUnit = 7 +}; + +enum AnimationConstants { + kTimeUnit = 20 }; /** Inventory related magical constants */ @@ -255,6 +262,8 @@ public: GameItem *getItem(int id) { return id >= 0 && id < (int) _info._numItems ? &_items[id] : NULL; } GameItem *getCurrentItem() const { return _currentItem; } void setCurrentItem(GameItem *item) { _currentItem = item; } + int getPreviousItemPosition() const { return _previousItemPosition; } + void setPreviousItemPosition(int pos) { _previousItemPosition = pos; } void removeItem(GameItem *item); void loadItemAnimation(GameItem *item); void putItem(GameItem *item, int position); @@ -292,6 +301,7 @@ public: void inventoryDraw(); void inventoryDone(); void inventoryReload(); + void inventorySwitch(int keycode); void dialogueMenu(int dialogueID); int dialogueDraw(); @@ -325,11 +335,13 @@ public: private: void updateOrdinaryCursor(); void updateInventoryCursor(); + int inventoryPositionFromMouse() const; void handleOrdinaryLoop(int x, int y); void handleInventoryLoop(); void handleDialogueLoop(); void updateTitle(int x, int y); void updateCursor(); + void fadePalette(bool fading_out); void advanceAnimationsAndTestLoopExit(); void handleStatusChangeByMouse(); @@ -353,6 +365,10 @@ private: GameItem *_currentItem; GameItem *_itemUnderCursor; + // Last position in the inventory of the item currently in the hands, resp. of the item that + // was last in our hands. + int _previousItemPosition; + GameItem *_inventory[kInventorySlots]; Room _currentRoom; diff --git a/engines/draci/script.cpp b/engines/draci/script.cpp index a366740526..7a6a68618d 100644 --- a/engines/draci/script.cpp +++ b/engines/draci/script.cpp @@ -553,6 +553,7 @@ void Script::icoStat(const Common::Array<int> ¶ms) { // arrow leading outside a location), set it to standard. if (_vm->_game->getCurrentItem() == item) { _vm->_game->setCurrentItem(NULL); + _vm->_game->setPreviousItemPosition(-1); if (_vm->_mouse->getCursorType() >= kItemCursor) { _vm->_mouse->setCursorType(kNormalCursor); } @@ -561,6 +562,7 @@ void Script::icoStat(const Common::Array<int> ¶ms) { } else { _vm->_game->loadItemAnimation(item); _vm->_game->setCurrentItem(item); + _vm->_game->setPreviousItemPosition(0); // next time, try to place the item from the beginning _vm->_mouse->loadItemCursor(item, false); } } @@ -727,10 +729,10 @@ void Script::talk(const Common::Array<int> ¶ms) { // Speak the dubbing if possible uint dubbingDuration = 0; if (sample) { - dubbingDuration = (uint) (1000.0 * sample->_length / sample->_frequency + 500.0); + dubbingDuration = _vm->_sound->playVoice(sample); debugC(3, kDraciSoundDebugLevel, "Playing sentence %d: %d+%d with duration %dms", sentenceID, sample->_offset, sample->_length, dubbingDuration); - _vm->_sound->playVoice(sample); + dubbingDuration += 500; } // Record time @@ -879,7 +881,7 @@ void Script::setPalette(const Common::Array<int> ¶ms) { } // Immediately update the palette _vm->_screen->copyToScreen(); - _vm->_system->delayMillis(20); + _vm->_system->delayMillis(kTimeUnit); } void Script::quitGame(const Common::Array<int> ¶ms) { diff --git a/engines/draci/sound.cpp b/engines/draci/sound.cpp index 4fb2fd6309..c9244d7eac 100644 --- a/engines/draci/sound.cpp +++ b/engines/draci/sound.cpp @@ -23,11 +23,13 @@ * */ +#include "common/archive.h" #include "common/config-manager.h" #include "common/debug.h" #include "common/file.h" #include "common/str.h" #include "common/stream.h" +#include "common/unzip.h" #include "draci/sound.h" #include "draci/draci.h" @@ -36,21 +38,24 @@ #include "sound/audiostream.h" #include "sound/mixer.h" #include "sound/decoders/raw.h" +#include "sound/decoders/mp3.h" +#include "sound/decoders/vorbis.h" +#include "sound/decoders/flac.h" namespace Draci { -void SoundArchive::openArchive(const Common::String &path) { +void LegacySoundArchive::openArchive(const char *path) { // Close previously opened archive (if any) closeArchive(); - debugCN(2, kDraciArchiverDebugLevel, "Loading samples %s: ", path.c_str()); + debugCN(1, kDraciArchiverDebugLevel, "Loading samples %s: ", path); _f = new Common::File(); _f->open(path); if (_f->isOpen()) { - debugC(2, kDraciArchiverDebugLevel, "Success"); + debugC(1, kDraciArchiverDebugLevel, "Success"); } else { - debugC(2, kDraciArchiverDebugLevel, "Error"); + debugC(1, kDraciArchiverDebugLevel, "Error"); delete _f; _f = NULL; return; @@ -60,7 +65,7 @@ void SoundArchive::openArchive(const Common::String &path) { _path = path; // Read archive header - debugC(2, kDraciArchiverDebugLevel, "Loading header"); + debugC(1, kDraciArchiverDebugLevel, "Loading header"); uint totalLength = _f->readUint32LE(); const uint kMaxSamples = 4095; // The no-sound file is exactly 16K bytes long, so don't fail on short reads @@ -76,26 +81,25 @@ void SoundArchive::openArchive(const Common::String &path) { break; } if (_sampleCount > 0) { - debugC(2, kDraciArchiverDebugLevel, "Archive info: %d samples, %d total length", + debugC(1, kDraciArchiverDebugLevel, "Archive info: %d samples, %d total length", _sampleCount, totalLength); _samples = new SoundSample[_sampleCount]; for (uint i = 0; i < _sampleCount; ++i) { _samples[i]._offset = sampleStarts[i]; _samples[i]._length = sampleStarts[i+1] - sampleStarts[i]; _samples[i]._frequency = 0; // set in getSample() - _samples[i]._data = NULL; } if (_samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length != totalLength && _samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length - _samples[0]._offset != totalLength) { // WORKAROUND: the stored length is stored with the header for sounds and without the hader for dubbing. Crazy. - debugC(2, kDraciArchiverDebugLevel, "Broken sound archive: %d != %d", + debugC(1, kDraciArchiverDebugLevel, "Broken sound archive: %d != %d", _samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length, totalLength); closeArchive(); return; } } else { - debugC(2, kDraciArchiverDebugLevel, "Archive info: empty"); + debugC(1, kDraciArchiverDebugLevel, "Archive info: empty"); } // Indicate that the archive has been successfully opened @@ -103,12 +107,12 @@ void SoundArchive::openArchive(const Common::String &path) { } /** - * @brief SoundArchive close method + * @brief LegacySoundArchive close method * * Closes the currently opened archive. It can be called explicitly to * free up memory. */ -void SoundArchive::closeArchive() { +void LegacySoundArchive::closeArchive() { clearCache(); delete _f; _f = NULL; @@ -123,7 +127,7 @@ void SoundArchive::closeArchive() { * Clears the cache of the open files inside the archive without closing it. * If the files are subsequently accessed, they are read from the disk. */ -void SoundArchive::clearCache() { +void LegacySoundArchive::clearCache() { // Delete all cached data for (uint i = 0; i < _sampleCount; ++i) { _samples[i].close(); @@ -137,32 +141,121 @@ void SoundArchive::clearCache() { * * Loads individual samples from an archive to memory on demand. */ -SoundSample *SoundArchive::getSample(int i, uint freq) { +SoundSample *LegacySoundArchive::getSample(int i, uint freq) { // Check whether requested file exists if (i < 0 || i >= (int) _sampleCount) { return NULL; } debugCN(2, kDraciArchiverDebugLevel, "Accessing sample %d from archive %s... ", - i, _path.c_str()); + i, _path); // Check if file has already been opened and return that if (_samples[i]._data) { - debugC(2, kDraciArchiverDebugLevel, "Success"); + debugC(2, kDraciArchiverDebugLevel, "Cached"); } else { + // It would be nice to unify the approach with ZipSoundArchive + // and allocate a MemoryReadStream with buffer stored inside it + // that playSoundBuffer() would just play. Unfortunately, + // streams are not thread-safe and the same sample couldn't + // thus be played more than once at the same time (this holds + // even if we create a SeekableSubReadStream from it as this + // just uses the parent). The only thread-safe solution is to + // share a read-only buffer and allocate separate + // MemoryReadStream's on top of it. + _samples[i]._data = new byte[_samples[i]._length]; + _samples[i]._format = RAW; + // Read in the file (without the file header) _f->seek(_samples[i]._offset); - _samples[i]._data = new byte[_samples[i]._length]; _f->read(_samples[i]._data, _samples[i]._length); - debugC(3, kDraciArchiverDebugLevel, "Cached sample %d from archive %s", - i, _path.c_str()); + debugC(2, kDraciArchiverDebugLevel, "Read sample %d from archive %s", + i, _path); } _samples[i]._frequency = freq ? freq : _defaultFreq; return _samples + i; } +void ZipSoundArchive::openArchive(const char *path, const char *extension, SoundFormat format, int raw_frequency) { + closeArchive(); + if ((format == RAW || format == RAW80) && !raw_frequency) { + error("openArchive() expects frequency for RAW data"); + return; + } + + debugCN(1, kDraciArchiverDebugLevel, "Trying to open ZIP archive %s: ", path); + _archive = Common::makeZipArchive(path); + _path = path; + _extension = extension; + _format = format; + _defaultFreq = raw_frequency; + + if (_archive) { + Common::ArchiveMemberList files; + _archive->listMembers(files); + _sampleCount = files.size(); + debugC(1, kDraciArchiverDebugLevel, "Capacity %d", _sampleCount); + } else { + debugC(1, kDraciArchiverDebugLevel, "Failed"); + } +} + +void ZipSoundArchive::closeArchive() { + clearCache(); + delete _archive; + _archive = NULL; + _path = _extension = NULL; + _sampleCount = _defaultFreq = 0; + _format = RAW; +} + +void ZipSoundArchive::clearCache() { + // Just deallocate the link-list of (very short) headers for each + // dubbed sentence played in the current location. If the callers have + // not called .close() on any of the items, call them now. + for (Common::List<SoundSample>::iterator it = _cache.begin(); it != _cache.end(); ++it) { + it->close(); + } + _cache.clear(); +} + +SoundSample *ZipSoundArchive::getSample(int i, uint freq) { + if (i < 0 || i >= (int) _sampleCount) { + return NULL; + } + debugCN(2, kDraciArchiverDebugLevel, "Accessing sample %d.%s from archive %s (format %d@%d, capacity %d): ", + i, _extension, _path, static_cast<int> (_format), _defaultFreq, _sampleCount); + if (freq != 0 && (_format != RAW && _format != RAW80)) { + error("Cannot resample a sound in compressed format"); + return NULL; + } + + // We cannot really cache anything, because createReadStreamForMember() + // returns the data as a ReadStream, which is not thread-safe. We thus + // read it again each time even if it has possibly been already cached + // a while ago. This is not such a problem for dubbing as for regular + // sound samples. + SoundSample sample; + sample._frequency = freq ? freq : _defaultFreq; + sample._format = _format; + // Read in the file (without the file header) + char file_name[20]; + sprintf(file_name, "%d.%s", i+1, _extension); + sample._stream = _archive->createReadStreamForMember(file_name); + if (!sample._stream) { + debugC(2, kDraciArchiverDebugLevel, "Doesn't exist"); + return NULL; + } else { + debugC(2, kDraciArchiverDebugLevel, "Read"); + _cache.push_back(sample); + // Return a pointer that we own and which we will deallocate + // including its contents. + return &_cache.back(); + } +} + Sound::Sound(Audio::Mixer *mixer) : _mixer(mixer), _muteSound(false), _muteVoice(false), _showSubtitles(true), _talkSpeed(kStandardSpeed) { @@ -192,28 +285,74 @@ SndHandle *Sound::getHandle() { return NULL; // for compilers that don't support NORETURN } -void Sound::playSoundBuffer(Audio::SoundHandle *handle, const SoundSample &buffer, int volume, +uint Sound::playSoundBuffer(Audio::SoundHandle *handle, const SoundSample &buffer, int volume, sndHandleType handleType, bool loop) { + if (!buffer._stream && !buffer._data) { + warning("Empty stream"); + return 0; + } + // Create a new SeekableReadStream which will be automatically disposed + // after the sample stops playing. Do not dispose the original + // data/stream though. + // Beware that if the sample comes from an archive (i.e., is stored in + // buffer._stream), then you must NOT play it more than once at the + // same time, because streams are not thread-safe. Playing it + // repeatedly is OK. Currently this is ensured by that archives are + // only used for dubbing, which is only played from one place in + // script.cpp, which blocks until the dubbed sentence has finished + // playing. + Common::SeekableReadStream* stream; + const int skip = buffer._format == RAW80 ? 80 : 0; + if (buffer._stream) { + stream = new Common::SeekableSubReadStream( + buffer._stream, skip, buffer._stream->size() /* end */, DisposeAfterUse::NO); + } else { + stream = new Common::MemoryReadStream( + buffer._data + skip, buffer._length - skip /* length */, DisposeAfterUse::NO); + } - byte flags = Audio::FLAG_UNSIGNED; + Audio::SeekableAudioStream *reader = NULL; + switch (buffer._format) { + case RAW: + case RAW80: + reader = Audio::makeRawStream(stream, buffer._frequency, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES); + break; +#ifdef USE_MAD + case MP3: + reader = Audio::makeMP3Stream(stream, DisposeAfterUse::YES); + break; +#endif +#ifdef USE_VORBIS + case OGG: + reader = Audio::makeVorbisStream(stream, DisposeAfterUse::YES); + break; +#endif +#ifdef USE_FLAC + case FLAC: + reader = Audio::makeFLACStream(stream, DisposeAfterUse::YES); + break; +#endif + default: + error("Unsupported compression format %d", static_cast<int> (buffer._format)); + delete stream; + return 0; + } + const uint length = reader->getLength().msecs(); const Audio::Mixer::SoundType soundType = (handleType == kVoiceHandle) ? Audio::Mixer::kSpeechSoundType : Audio::Mixer::kSFXSoundType; - - // Don't use DisposeAfterUse::YES, because our caching system deletes samples by itself. - Audio::AudioStream *stream = Audio::makeLoopingAudioStream( - Audio::makeRawStream(buffer._data, buffer._length, buffer._frequency, flags, DisposeAfterUse::NO), - loop ? 0 : 1); - _mixer->playStream(soundType, handle, stream, -1, volume); + Audio::AudioStream *audio_stream = Audio::makeLoopingAudioStream(reader, loop ? 0 : 1); + _mixer->playStream(soundType, handle, audio_stream, -1, volume); + return length; } -void Sound::playSound(const SoundSample *buffer, int volume, bool loop) { +uint Sound::playSound(const SoundSample *buffer, int volume, bool loop) { if (!buffer || _muteSound) - return; + return 0; SndHandle *handle = getHandle(); handle->type = kEffectHandle; - playSoundBuffer(&handle->handle, *buffer, 2 * volume, handle->type, loop); + return playSoundBuffer(&handle->handle, *buffer, 2 * volume, handle->type, loop); } void Sound::pauseSound() { @@ -237,13 +376,13 @@ void Sound::stopSound() { } } -void Sound::playVoice(const SoundSample *buffer) { +uint Sound::playVoice(const SoundSample *buffer) { if (!buffer || _muteVoice) - return; + return 0; SndHandle *handle = getHandle(); handle->type = kVoiceHandle; - playSoundBuffer(&handle->handle, *buffer, Audio::Mixer::kMaxChannelVolume, handle->type, false); + return playSoundBuffer(&handle->handle, *buffer, Audio::Mixer::kMaxChannelVolume, handle->type, false); } void Sound::pauseVoice() { diff --git a/engines/draci/sound.h b/engines/draci/sound.h index 28379b5429..6e9aae1b6e 100644 --- a/engines/draci/sound.h +++ b/engines/draci/sound.h @@ -28,50 +28,101 @@ #include "common/str.h" #include "common/file.h" +#include "common/list.h" #include "sound/mixer.h" +namespace Common { +class Archive; +class SeekableReadStream; +} + namespace Draci { +enum SoundFormat { RAW, RAW80, MP3, OGG, FLAC }; // RAW80 means skip the first 80 bytes + /** * Represents individual files inside the archive. */ struct SoundSample { - uint _offset; + uint _offset; // For internal use of LegacySoundArchive uint _length; - uint _frequency; - byte* _data; + uint _frequency; // Only when _format == RAW or RAW80 + SoundFormat _format; + + byte *_data; // At most one of these two pointer can be non-NULL + Common::SeekableReadStream* _stream; + + SoundSample() : _offset(0), _length(0), _frequency(0), _format(RAW), _data(NULL), _stream(NULL) { } + // The standard copy constructor is good enough, since we only store numbers and pointers. + // Don't call close() automaticall in the destructor, otherwise copying causes SIGSEGV. void close() { delete[] _data; + delete _stream; _data = NULL; + _stream = NULL; } }; +/** + * An abstract wrapper around archives of sound samples or dubbing. + */ class SoundArchive { public: - SoundArchive(const Common::String &path, uint defaultFreq) : - _path(), _samples(NULL), _sampleCount(0), _defaultFreq(defaultFreq), _opened(false), _f(NULL) { - openArchive(path); - } + SoundArchive() { } + virtual ~SoundArchive() { } - ~SoundArchive() { closeArchive(); } - - void closeArchive(); - void openArchive(const Common::String &path); - uint size() const { return _sampleCount; } + /** + * Returns the number of sound samples in the archive. Zero means that + * a fake empty archive has been opened and the caller may consider + * opening a different one, for example with compressed music. + */ + virtual uint size() const = 0; /** * Checks whether there is an archive opened. Should be called before reading - * from the archive to check whether openArchive() succeeded. + * from the archive to check whether opening of the archive has succeeded. + */ + virtual bool isOpen() const = 0; + + /** + * Removes cached samples from memory. */ - bool isOpen() const { return _opened; } + virtual void clearCache() = 0; + + /** + * Caches a given sample into memory and returns a pointer into it. We + * own the returned pointer, but the user may call .close() on it, + * which deallocates the memory of the actual sample data. If freq is + * nonzero, then the sample is played at a different frequency (only + * works for uncompressed samples). + */ + virtual SoundSample *getSample(int i, uint freq) = 0; +}; - void clearCache(); +/** + * Reads CD.SAM (with dubbing) and CD2.SAM (with sound samples) from the + * original game. Caches all read samples in a thread-safe manner. + */ +class LegacySoundArchive : public SoundArchive { +public: + LegacySoundArchive(const char *path, uint defaultFreq) : + _path(NULL), _samples(NULL), _sampleCount(0), _defaultFreq(defaultFreq), _opened(false), _f(NULL) { + openArchive(path); + } + virtual ~LegacySoundArchive() { closeArchive(); } - SoundSample *getSample(int i, uint freq); + void openArchive(const char *path); + void closeArchive(); + + virtual uint size() const { return _sampleCount; } + virtual bool isOpen() const { return _opened; } + + virtual void clearCache(); + virtual SoundSample *getSample(int i, uint freq); private: - Common::String _path; ///< Path to file + const char *_path; ///< Path to file SoundSample *_samples; ///< Internal array of files uint _sampleCount; ///< Number of files in archive uint _defaultFreq; ///< The default sampling frequency of the archived samples @@ -79,6 +130,44 @@ private: Common::File *_f; ///< Opened file }; +/** + * Reads ZIP archives with uncompressed files containing lossy-compressed + * samples in arbitrary format. Doesn't do any real caching and is + * thread-safe. + */ +class ZipSoundArchive : public SoundArchive { +public: + ZipSoundArchive() : _archive(NULL), _path(NULL), _extension(NULL), _format(RAW), _sampleCount(0), _defaultFreq(0), _cache() { } + virtual ~ZipSoundArchive() { closeArchive(); } + + void openArchive(const char *path, const char *extension, SoundFormat format, int raw_frequency = 0); + void closeArchive(); + + virtual uint size() const { return _sampleCount; } + virtual bool isOpen() const { return _archive != NULL; } + + virtual void clearCache(); + virtual SoundSample *getSample(int i, uint freq); + +private: + Common::Archive *_archive; + const char *_path; + const char *_extension; + SoundFormat _format; + uint _sampleCount; + uint _defaultFreq; + + // Since we typically play at most 1 dubbing at a time, we could get + // away with having just 1 record allocated and reusing it each time. + // However, that would be thread-unsafe if two samples were played. + // Although the player does not do that, it is nicer to allow for it in + // principle. For each dubbed sentence, we allocate a new record in + // the following link-list, which is cleared during each location + // change. The dubbed samples themselves are manually deallocated + // after they end. + Common::List<SoundSample> _cache; +}; + #define SOUND_HANDLES 10 enum sndHandleType { @@ -100,13 +189,13 @@ public: Sound(Audio::Mixer *mixer); ~Sound() {} - void playSound(const SoundSample *buffer, int volume, bool loop); + uint playSound(const SoundSample *buffer, int volume, bool loop); void pauseSound(); void resumeSound(); void stopSound(); bool isMutedSound() const { return _muteSound; } - void playVoice(const SoundSample *buffer); + uint playVoice(const SoundSample *buffer); void pauseVoice(); void resumeVoice(); void stopVoice(); @@ -120,7 +209,8 @@ public: int talkSpeed() const { return _talkSpeed; } private: - void playSoundBuffer(Audio::SoundHandle *handle, const SoundSample &buffer, int volume, + // Returns the length of the sound sample in miliseconds. + uint playSoundBuffer(Audio::SoundHandle *handle, const SoundSample &buffer, int volume, sndHandleType handleType, bool loop); SndHandle *getHandle(); diff --git a/engines/drascula/actors.cpp b/engines/drascula/actors.cpp index ff46d8201a..33cb7fd478 100644 --- a/engines/drascula/actors.cpp +++ b/engines/drascula/actors.cpp @@ -77,6 +77,7 @@ void DrasculaEngine::hiccup(int counter) { do { counter--; + updateEvents(); updateRoom(); if (currentChapter == 3) updateScreen(0, 0, 0, y, 320, 200, screenSurface); @@ -99,6 +100,7 @@ void DrasculaEngine::hiccup(int counter) { if (y == 0) trackCharacter = 0; } + pause(3); } while (counter > 0); updateRoom(); @@ -449,6 +451,7 @@ void DrasculaEngine::placeVonBraun(int pointX) { vonBraunHasMoved = 1; for (;;) { + updateEvents(); updateRoom(); updateScreen(); if (trackVonBraun == 0) { diff --git a/engines/drascula/animation.cpp b/engines/drascula/animation.cpp index e4bd844d75..d6a3bafd9f 100644 --- a/engines/drascula/animation.cpp +++ b/engines/drascula/animation.cpp @@ -32,17 +32,23 @@ void DrasculaEngine::updateAnim(int y, int destX, int destY, int width, int heig for (int n = 0; n < count; n++){ x++; - copyBackground(x, y, destX, destY, width, height, src, screenSurface); - if (copyRectangle) + if (copyRectangle) { + copyBackground(destX, destY, destX, destY, width, height, bgSurface, screenSurface); copyRect(x, y, destX, destY, width, height, src, screenSurface); + } else { + copyBackground(x, y, destX, destY, width, height, src, screenSurface); + } updateScreen(destX, destY, destX, destY, width, height, screenSurface); x += width; + updateEvents(); pause(delayVal); } } // This is the game's introduction sequence void DrasculaEngine::animation_1_1() { + debug(4, "animation_1_1()"); + int l, l2, p; //int pixelPos[6]; @@ -141,9 +147,9 @@ void DrasculaEngine::animation_1_1() { copyBackground(0, 0, 320 - l, 0, l, 200, drawSurface3, screenSurface); copyBackground(l, 0, 0, 0, 320 - l, 200, bgSurface, screenSurface); - copyRect(interf_x[l2], interf_y[l2], 156 - l, 45, 63, 31, - drawSurface2, screenSurface); + copyRect(interf_x[l2], interf_y[l2], 156 - l, 45, 63, 31, drawSurface2, screenSurface); updateScreen(); + updateEvents(); p++; if (p == 6) { p = 0; @@ -371,6 +377,8 @@ void DrasculaEngine::animation_1_1() { // John falls in love with BJ, who is then abducted by Drascula void DrasculaEngine::animation_2_1() { + debug(4, "animation_2_1()"); + int l; gotoObject(231, 91); @@ -560,6 +568,8 @@ void DrasculaEngine::animation_2_1() { // John Hacker talks with the bartender to book a room void DrasculaEngine::animation_3_1() { + debug(4, "animation_3_1()"); + loadPic("an11y13.alg", extraSurface); playTalkSequence(3); // sequence 3, chapter 1 @@ -569,6 +579,8 @@ void DrasculaEngine::animation_3_1() { // John Hacker talks with the pianist void DrasculaEngine::animation_4_1() { + debug(4, "animation_4_1()"); + loadPic("an12.alg", extraSurface); talk(205); @@ -605,6 +617,8 @@ void DrasculaEngine::animation_4_1() { } void DrasculaEngine::animation_2_2() { + debug(4, "animation_2_2()"); + trackProtagonist = 0; copyBackground(); moveCharacters(); @@ -640,6 +654,8 @@ void DrasculaEngine::animation_2_2() { } void DrasculaEngine::animation_4_2() { + debug(4, "animation_4_2()"); + stopMusic(); flags[9] = 1; @@ -704,6 +720,8 @@ void DrasculaEngine::animation_4_2() { } void DrasculaEngine::animation_14_2() { + debug(4, "animation_14_2()"); + int cY = -160; int l = 0; @@ -735,6 +753,8 @@ void DrasculaEngine::animation_14_2() { // The drunk tells us about Von Braun void DrasculaEngine::animation_16_2() { + debug(4, "animation_16_2()"); + char curPic[20]; talk_drunk(12); talk(371); @@ -812,6 +832,8 @@ asco: } void DrasculaEngine::animation_20_2() { + debug(4, "animation_20_2()"); + talk_vonBraun(7, kVonBraunDoor); talk_vonBraun(8, kVonBraunDoor); talk(383); @@ -842,6 +864,8 @@ void DrasculaEngine::animation_20_2() { } void DrasculaEngine::animation_23_2() { + debug(4, "animation_23_2()"); + loadPic("an24.alg", frontSurface); flags[21] = 1; @@ -897,6 +921,8 @@ void DrasculaEngine::animation_23_2() { } void DrasculaEngine::animation_23_joined() { + debug(4, "animation_23_joined()"); + int p_x = curX + 2, p_y = curY - 3; int x[] = {1, 38, 75, 112, 75, 112, 75, 112, 149, 112, 149, 112, 149, 186, 223, 260, 1, 38, 75, 112, 149, 112, 149, 112, 149, 112, 149, 186, 223, 260, 260, 260, 260, 223}; @@ -910,6 +936,7 @@ void DrasculaEngine::animation_23_joined() { copyRect(x[n], y[n], p_x, p_y, 36, 74, backSurface, screenSurface); updateRefresh(); updateScreen(p_x, p_y, p_x, p_y, 36, 74, screenSurface); + updateEvents(); pause(5); } @@ -917,6 +944,8 @@ void DrasculaEngine::animation_23_joined() { } void DrasculaEngine::animation_23_joined2() { + debug(4, "animation_23_joined2()"); + int p_x = curX + 4, p_y = curY; int x[] = {1, 35, 69, 103, 137, 171, 205, 239, 273, 1, 35, 69, 103, 137}; int y[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 73, 73, 73, 73, 73}; @@ -930,6 +959,7 @@ void DrasculaEngine::animation_23_joined2() { copyRect(x[n], y[n], p_x, p_y, 33, 71, backSurface, screenSurface); updateRefresh(); updateScreen(p_x,p_y, p_x,p_y, 33,71, screenSurface); + updateEvents(); pause(5); } @@ -937,6 +967,8 @@ void DrasculaEngine::animation_23_joined2() { } void DrasculaEngine::animation_25_2() { + debug(4, "animation_25_2()"); + int cY = 0; loadPic("an14_2.alg", backSurface); @@ -959,6 +991,7 @@ void DrasculaEngine::animation_25_2() { updateRefresh(); updateScreen(); + updateEvents(); } finishSound(); @@ -967,6 +1000,8 @@ void DrasculaEngine::animation_25_2() { } void DrasculaEngine::animation_27_2() { + debug(4, "animation_27_2()"); + flags[22] = 1; selectVerb(kVerbNone); @@ -986,6 +1021,8 @@ void DrasculaEngine::animation_27_2() { } void DrasculaEngine::animation_29_2() { + debug(4, "animation_29_2()"); + if (flags[33] == 0) { playTalkSequence(29); // sequence 29, chapter 2 } else @@ -1002,6 +1039,8 @@ void DrasculaEngine::animation_29_2() { } void DrasculaEngine::animation_31_2() { + debug(4, "animation_31_2()"); + talk_vonBraun(44, kVonBraunNormal); placeVonBraun(-50); pause(15); @@ -1020,6 +1059,8 @@ void DrasculaEngine::animation_31_2() { } void DrasculaEngine::animation_35_2() { + debug(4, "animation_35_2()"); + gotoObject(96, 165); gotoObject(79, 165); @@ -1049,7 +1090,10 @@ void DrasculaEngine::animation_35_2() { fadeToBlack(2); } +// Use cross on Yoda void DrasculaEngine::animation_2_3() { + debug(4, "animation_2_3()"); + flags[0] = 1; playMusic(13); animation_3_3(); @@ -1070,6 +1114,8 @@ void DrasculaEngine::animation_2_3() { } void DrasculaEngine::animation_3_3() { + debug(4, "animation_3_3()"); + int px = curX - 20, py = curY - 1; loadPic("an2y_1.alg", frontSurface); @@ -1085,6 +1131,8 @@ void DrasculaEngine::animation_3_3() { } void DrasculaEngine::animation_4_3() { + debug(4, "animation_4_3()"); + int px = 120, py = 63; loadPic("any_1.alg", frontSurface); @@ -1100,6 +1148,8 @@ void DrasculaEngine::animation_4_3() { } void DrasculaEngine::animation_5_3() { + debug(4, "animation_5_3()"); + int px = curX - 20, py = curY - 1; loadPic("an3y_1.alg", frontSurface); @@ -1115,6 +1165,8 @@ void DrasculaEngine::animation_5_3() { } void DrasculaEngine::animation_6_3() { + debug(4, "animation_6_3()"); + int frame = 0, px = 112, py = 62; int yoda_x[] = { 3 ,82, 161, 240, 3, 82 }; int yoda_y[] = { 3, 3, 3, 3, 94, 94 }; @@ -1133,6 +1185,7 @@ void DrasculaEngine::animation_6_3() { copyBackground(); copyRect(yoda_x[frame], yoda_y[frame], px, py, 78, 90, frontSurface, screenSurface); updateScreen(px, py, px, py, 78, 90, screenSurface); + updateEvents(); } flags[2] = 1; @@ -1144,6 +1197,8 @@ void DrasculaEngine::animation_6_3() { } void DrasculaEngine::animation_ray() { + debug(4, "animation_ray()"); + loadPic("anr_1.alg", frontSurface, HALF_PAL); loadPic("anr_2.alg", extraSurface); loadPic("anr_3.alg", backSurface); @@ -1171,6 +1226,8 @@ void DrasculaEngine::animation_ray() { } void DrasculaEngine::animation_7_4() { + debug(4, "animation_7_4()"); + black(); talk(427); fadeFromBlack(1); @@ -1184,6 +1241,8 @@ void DrasculaEngine::animation_7_4() { } void DrasculaEngine::animation_1_5() { + debug(4, "animation_1_5()"); + if (flags[0] == 0) { talk(430); talk_bj(16); @@ -1212,6 +1271,7 @@ void DrasculaEngine::animation_1_5() { break; updateRoom(); updateScreen(); + updateEvents(); } trackProtagonist = 1; @@ -1224,6 +1284,8 @@ void DrasculaEngine::animation_1_5() { } void DrasculaEngine::animation_5_5(){ + debug(4, "animation_5_5("); + int h; int frame = 0; int boneX[] = {1, 99, 197, 1, 99, 197, 1, 99, 197}; @@ -1247,6 +1309,7 @@ void DrasculaEngine::animation_5_5(){ copyBackground(); copyRect(boneX[frame], boneY[frame], pixelX, pixelY, 97, 64, backSurface, screenSurface); updateScreen(pixelX, pixelY, pixelX,pixelY, 97,64, screenSurface); + updateEvents(); } copyBackground(52, 161, 198, 81, 26, 24, drawSurface3, screenSurface); @@ -1257,6 +1320,7 @@ void DrasculaEngine::animation_5_5(){ copyBackground(); copyRect(boneX[frame], boneY[frame], pixelX, pixelY, 97, 64, frontSurface, screenSurface); updateScreen(pixelX, pixelY, pixelX,pixelY, 97, 64, screenSurface); + updateEvents(); } flags[6] = 1; @@ -1279,11 +1343,13 @@ void DrasculaEngine::animation_5_5(){ pause(3); copyBackground(flyX[frame], 1, 174, 79, 61, 109, backSurface, screenSurface); updateScreen(174, 79, 174, 79, 61, 109, screenSurface); + updateEvents(); } for (frame = 0; frame < 5; frame++) { pause(3); copyBackground(flyX[frame], 1, 174, 79, 61, 109, extraSurface, screenSurface); updateScreen(174, 79, 174, 79, 61, 109, screenSurface); + updateEvents(); } updateScreen(0, 0, 0, 0, 320, 200, bgSurface); @@ -1299,6 +1365,8 @@ void DrasculaEngine::animation_5_5(){ } void DrasculaEngine::animation_11_5() { + debug(4, "animation_11_5()"); + flags[9] = 1; if (flags[2] == 1 && flags[3] == 1 && flags[4] == 1) animation_12_5(); @@ -1309,6 +1377,8 @@ void DrasculaEngine::animation_11_5() { } void DrasculaEngine::animation_12_5() { + debug(4, "animation_12_5()"); + DacPalette256 bgPalette1; DacPalette256 bgPalette2; DacPalette256 bgPalette3; @@ -1367,6 +1437,7 @@ void DrasculaEngine::animation_12_5() { copyRect(rayX[frame], 1, 41, 0, 44, 44, backSurface, screenSurface); copyRect(frusky_x[frame], 113, 205, 50, 38, 86, drawSurface3, screenSurface); updateScreen(); + updateEvents(); } stopSound(); @@ -1383,6 +1454,7 @@ void DrasculaEngine::animation_12_5() { updateRoom(); copyRect(elfrusky_x[frame], 47, 192, 39, 66, 106, backSurface, screenSurface); updateScreen(); + updateEvents(); } animate("frel.bin", 16); @@ -1415,6 +1487,8 @@ void DrasculaEngine::animation_12_5() { } void DrasculaEngine::animation_13_5() { + debug(4, "animation_13_5()"); + int frank_x = 199; int frame = 0; int frus_x[] = {1, 46, 91, 136, 181, 226, 271}; @@ -1441,11 +1515,14 @@ void DrasculaEngine::animation_13_5() { frame = 0; trackProtagonist = 3; } + updateEvents(); pause(6); } } void DrasculaEngine::animation_14_5() { + debug(4, "animation_14_5()"); + flags[11] = 1; playSound(3); updateRoom(); @@ -1469,6 +1546,8 @@ void DrasculaEngine::animation_14_5() { } void DrasculaEngine::animation_1_6() { + debug(4, "animation_1_6()"); + trackProtagonist = 0; curX = 103; curY = 108; @@ -1497,11 +1576,15 @@ void DrasculaEngine::animation_1_6() { talk_drascula(28, 1); talk(255); talk_drascula(29, 1); + updateEvents(); fadeToBlack(1); + updateEvents(); clearRoom(); loadPic("time1.alg", screenSurface); updateScreen(); + updateEvents(); delay(930); + updateEvents(); clearRoom(); black(); hare_se_ve = 0; @@ -1513,10 +1596,13 @@ void DrasculaEngine::animation_1_6() { talk_drascula(30, 1); talk(257); fadeToBlack(0); + updateEvents(); clearRoom(); loadPic("time1.alg", screenSurface); updateScreen(); + updateEvents(); delay(900); + updateEvents(); clearRoom(); black(); updateRoom(); @@ -1540,6 +1626,8 @@ void DrasculaEngine::animation_1_6() { } void DrasculaEngine::animation_5_6() { + debug(4, "animation_5_6()"); + int pY = -125; animate("man.bin", 14); @@ -1553,6 +1641,7 @@ void DrasculaEngine::animation_5_6() { updateRefresh(); updateScreen(); + updateEvents(); pause(2); } @@ -1560,6 +1649,8 @@ void DrasculaEngine::animation_5_6() { } void DrasculaEngine::animation_6_6() { + debug(4, "animation_6_6()"); + animate("rct.bin", 11); clearRoom(); selectVerb(kVerbNone); @@ -1584,6 +1675,8 @@ void DrasculaEngine::animation_6_6() { } void DrasculaEngine::animation_9_6() { + debug(4, "animation_9_6()"); + int v_cd; animate("fin.bin", 14); @@ -1660,6 +1753,8 @@ void DrasculaEngine::animation_9_6() { } void DrasculaEngine::animation_19_6() { + debug(4, "animation_19_6()"); + copyBackground(); copyBackground(140, 23, 161, 69, 35, 80, drawSurface3, screenSurface); @@ -1675,6 +1770,8 @@ void DrasculaEngine::animation_19_6() { } void DrasculaEngine::animation_12_2() { + debug(4, "animation_12_2()"); + loadPic("an12.alg", extraSurface); talk(356); @@ -1705,6 +1802,8 @@ void DrasculaEngine::animation_12_2() { } void DrasculaEngine::animation_26_2() { + debug(4, "animation_26_2()"); + loadPic("an12.alg", extraSurface); talk(392); @@ -1745,6 +1844,7 @@ void DrasculaEngine::animation_26_2() { x = x + 50; if (n == 2) playSound(9); + updateEvents(); pause(3); } @@ -1762,6 +1862,8 @@ void DrasculaEngine::animation_26_2() { } void DrasculaEngine::animation_11_2() { + debug(4, "animation_11_2()"); + loadPic("an11y13.alg", extraSurface); playTalkSequence(11); // sequence 11, chapter 2 @@ -1770,6 +1872,8 @@ void DrasculaEngine::animation_11_2() { } void DrasculaEngine::animation_13_2() { + debug(4, "animation_13_2()"); + loadPic("an11y13.alg", frontSurface); if (flags[41] == 0) { @@ -1780,6 +1884,8 @@ void DrasculaEngine::animation_13_2() { } void DrasculaEngine::animation_24_2() { + debug(4, "animation_24_2()"); + if (curX < 178) gotoObject(208, 136); trackProtagonist = 3; @@ -1810,6 +1916,8 @@ void DrasculaEngine::animation_24_2() { } void DrasculaEngine::animation_32_2() { + debug(4, "animation_32_2()"); + loadPic("an32_1.alg", drawSurface3); loadPic("an32_2.alg", backSurface); @@ -1825,12 +1933,16 @@ void DrasculaEngine::animation_32_2() { x = x + 65; if (n < 2) pause(4); + + updateEvents(); } loadPic("aux18.alg", drawSurface3); } void DrasculaEngine::animation_34_2() { + debug(4, "animation_34_2()"); + trackProtagonist = 1; updateRoom(); updateScreen(); @@ -1858,6 +1970,8 @@ void DrasculaEngine::animation_34_2() { } void DrasculaEngine::animation_36_2() { + debug(4, "animation_36_2()"); + loadPic("an11y13.alg", extraSurface); talk(404); @@ -1871,7 +1985,10 @@ void DrasculaEngine::animation_36_2() { loadPic(974, extraSurface); } +// Use sickle on plant void DrasculaEngine::animation_7_2() { + debug(4, "animation_7_2()"); + loadPic("an7_1.alg", backSurface); loadPic("an7_2.alg", extraSurface); loadPic("an7_3.alg", frontSurface); @@ -1928,6 +2045,8 @@ void DrasculaEngine::animation_7_2() { } void DrasculaEngine::animation_5_2() { + debug(4, "animation_5_2()"); + trackProtagonist = 0; updateRoom(); updateScreen(); @@ -1964,6 +2083,8 @@ void DrasculaEngine::animation_5_2() { } void DrasculaEngine::animation_6_2() { + debug(4, "animation_6_2()"); + stopMusic(); flags[9] = 1; @@ -2005,6 +2126,8 @@ void DrasculaEngine::animation_6_2() { } void DrasculaEngine::animation_33_2() { + debug(4, "animation_33_2()"); + stopMusic(); flags[9] = 1; @@ -2052,6 +2175,8 @@ void DrasculaEngine::animation_33_2() { } void DrasculaEngine::animation_1_4() { + debug(4, "animation_1_4()"); + if (flags[21] == 0) { strcpy(objName[2], "igor"); talk(275); @@ -2108,6 +2233,8 @@ void DrasculaEngine::animation_1_4() { } void DrasculaEngine::animation_5_4(){ + debug(4, "animation_5_4("); + trackProtagonist = 3; loadPic("anh_dr.alg", backSurface); gotoObject(99, 160); @@ -2136,6 +2263,8 @@ void DrasculaEngine::animation_5_4(){ } void DrasculaEngine::animation_6_4() { + debug(4, "animation_6_4()"); + int prevRoom = roomNumber; roomNumber = 26; @@ -2161,6 +2290,8 @@ void DrasculaEngine::animation_6_4() { } void DrasculaEngine::animation_8_4() { + debug(4, "animation_8_4()"); + int bookcaseX[] = {1, 75, 149, 223, 1, 75, 149, 223, 149, 223, 149, 223, 149, 223}; int bookcaseY[] = {1, 1, 1, 1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74}; @@ -2170,6 +2301,7 @@ void DrasculaEngine::animation_8_4() { pause(2); copyBackground(bookcaseX[frame], bookcaseY[frame], 77, 45, 73, 72, frontSurface, screenSurface); updateScreen(77, 45, 77, 45, 73, 72, screenSurface); + updateEvents(); } loadPic(96, frontSurface); @@ -2177,6 +2309,8 @@ void DrasculaEngine::animation_8_4() { } void DrasculaEngine::activatePendulum() { + debug(4, "activatePendulum()"); + flags[1] = 2; hare_se_ve = 0; roomNumber = 102; diff --git a/engines/sci/graphics/gui32.h b/engines/drascula/console.cpp index 99eb03b321..d017468285 100644 --- a/engines/sci/graphics/gui32.h +++ b/engines/drascula/console.cpp @@ -23,46 +23,41 @@ * */ -#ifndef SCI_GRAPHICS_GUI32_H -#define SCI_GRAPHICS_GUI32_H +#include "drascula/console.h" +#include "gui/debugger.h" +#include "drascula/drascula.h" -#include "sci/graphics/helpers.h" +namespace Drascula { -namespace Sci { +Console::Console(DrasculaEngine *vm) : GUI::Debugger(), _vm(vm) { + DCmd_Register("room", WRAP_METHOD(Console, Cmd_Room)); +} -class GfxCursor; -class GfxScreen; -class GfxPalette; -class GfxCache; -class GfxCoordAdjuster32; -class GfxCompare; -class GfxFrameout; -class GfxPaint32; +Console::~Console() { +} -class SciGui32 { -public: - SciGui32(SegManager *segMan, SciEvent *event, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor); - ~SciGui32(); +void Console::preEnter() { +} - void init(); +void Console::postEnter() { +} - void textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight); +bool Console::Cmd_Room(int argc, const char **argv) { + if (argc < 2) { + DebugPrintf("Usage: changeCard <card>\n"); + return true; + } - void drawRobot(GuiResourceId robotId); + int roomNum = atoi(argv[1]); -protected: - GfxCursor *_cursor; - GfxScreen *_screen; - GfxPalette *_palette; - GfxCache *_cache; - GfxCoordAdjuster32 *_coordAdjuster; - GfxCompare *_compare; - GfxFrameout *_frameout; - GfxPaint32 *_paint32; + _vm->loadedDifferentChapter = 0; + _vm->enterRoom(roomNum); + _vm->selectVerb(kVerbNone); + _vm->clearRoom(); + _vm->loadPic(roomNum, _vm->bgSurface, HALF_PAL); + _vm->selectionMade = 0; -private: -}; + return false; +} -} // End of namespace Sci - -#endif +} // End of namespace Drascula diff --git a/backends/platform/ds/arm9/source/portdefs.cpp b/engines/drascula/console.h index 0dcdc1d5a3..33e2f626e4 100644 --- a/backends/platform/ds/arm9/source/portdefs.cpp +++ b/engines/drascula/console.h @@ -8,28 +8,44 @@ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ * */ -#include <string.h> -#include "nds/dma.h" -#include "osystem_ds.h" +#ifndef DRASCULA_CONSOLE_H +#define DRASCULA_CONSOLE_H + +#include "gui/debugger.h" + +namespace Drascula { + +class DrasculaEngine; + +class Console : public GUI::Debugger { +public: + Console(DrasculaEngine *vm); + virtual ~Console(void); + +protected: + virtual void preEnter(); + virtual void postEnter(); + +private: + DrasculaEngine *_vm; -/* -extern "C" time_t __wrap_time(time_t* t) { - if (t) { - *t = OSystem_DS::instance()->getMillis() / 1000; - } + bool Cmd_Room(int argc, const char **argv); +}; - return OSystem_DS::instance()->getMillis() / 1000; -} -*/ +} // End of namespace Drascula +#endif diff --git a/engines/drascula/converse.cpp b/engines/drascula/converse.cpp index b2a7e217e6..0e70348148 100644 --- a/engines/drascula/converse.cpp +++ b/engines/drascula/converse.cpp @@ -131,6 +131,8 @@ void DrasculaEngine::cleanupString(char *string) { } void DrasculaEngine::converse(int index) { + debug(4, "converse(%d)", index); + char fileName[20]; sprintf(fileName, "op_%d.cal", index); Common::SeekableReadStream *stream = _archives.open(fileName); @@ -279,9 +281,15 @@ void DrasculaEngine::converse(int index) { } void DrasculaEngine::response(int function) { - playTalkSequence(function); + debug(4, "response(%d)", function); + + if (function != 31) + playTalkSequence(function); if (currentChapter == 2) { + if (function == 16 || function == 20 || function == 23 || function == 29 || function == 31) + loadPic(menuBackground, backSurface); + if (function == 16) animation_16_2(); else if (function == 20) diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp index 76d48b7b89..c10222cadd 100644 --- a/engines/drascula/detection.cpp +++ b/engines/drascula/detection.cpp @@ -264,7 +264,11 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NOMIDI + Common::GUIO_NOMIDI, + // Maximum directory depth + 1, + // List of directory globs + 0 }; class DrasculaMetaEngine : public AdvancedMetaEngine { diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp index 39f07e5875..7c87f3574d 100644 --- a/engines/drascula/drascula.cpp +++ b/engines/drascula/drascula.cpp @@ -38,6 +38,7 @@ #include "sound/mixer.h" #include "drascula/drascula.h" +#include "drascula/console.h" namespace Drascula { @@ -115,6 +116,8 @@ DrasculaEngine::~DrasculaEngine() { freeRoomsTable(); + delete _console; + free(_charMap); free(_itemLocations); free(_polX); @@ -173,6 +176,8 @@ Common::Error DrasculaEngine::run() { _lang = kEnglish; } + _console = new Console(this); + if (!loadDrasculaDat()) return Common::kUnknownError; @@ -241,6 +246,8 @@ Common::Error DrasculaEngine::run() { if (currentChapter != 3) loadPic(96, frontSurface, COMPLETE_PAL); + loadPic(99, cursorSurface); + if (currentChapter == 1) { } else if (currentChapter == 2) { loadPic("pts.alg", drawSurface2); @@ -272,6 +279,7 @@ Common::Error DrasculaEngine::run() { loadPic(974, tableSurface); if (currentChapter != 2) { + loadPic(99, cursorSurface); loadPic(99, backSurface); loadPic(97, extraSurface); } @@ -499,11 +507,15 @@ bool DrasculaEngine::runCurrentChapter() { #else if (rightMouseButton == 1 && _menuScreen) { #endif + rightMouseButton = 0; delay(100); - if (currentChapter == 2) + if (currentChapter == 2) { + loadPic(menuBackground, cursorSurface); loadPic(menuBackground, backSurface); - else + } else { + loadPic(99, cursorSurface); loadPic(99, backSurface); + } setPalette((byte *)&gamePalette); _menuScreen = false; #ifndef _WIN32_WCE @@ -524,18 +536,24 @@ bool DrasculaEngine::runCurrentChapter() { if (rightMouseButton == 1 && !_menuScreen && !(currentChapter == 5 && pickedObject == 16)) { #endif + rightMouseButton = 0; delay(100); characterMoved = 0; if (trackProtagonist == 2) trackProtagonist = 1; - if (currentChapter == 4) + if (currentChapter == 4) { loadPic("icons2.alg", backSurface); - else if (currentChapter == 5) + loadPic("icons2.alg", cursorSurface); + } else if (currentChapter == 5) { loadPic("icons3.alg", backSurface); - else if (currentChapter == 6) + loadPic("icons3.alg", cursorSurface); + } else if (currentChapter == 6) { loadPic("iconsp.alg", backSurface); - else + loadPic("iconsp.alg", cursorSurface); + } else { loadPic("icons.alg", backSurface); + loadPic("icons.alg", cursorSurface); + } _menuScreen = true; #ifndef _WIN32_WCE updateEvents(); @@ -594,6 +612,9 @@ bool DrasculaEngine::runCurrentChapter() { } else if (key == Common::KEYCODE_ESCAPE) { if (!confirmExit()) return false; + } else if (key == Common::KEYCODE_TILDE || key == Common::KEYCODE_BACKQUOTE) { + _console->attach(); + _console->onFrame(); } else if (currentChapter == 6 && key == Common::KEYCODE_0 && roomNumber == 61) { loadPic("alcbar.alg", bgSurface, 255); } @@ -741,10 +762,10 @@ void DrasculaEngine::updateEvents() { leftMouseButton = 0; break; case Common::EVENT_RBUTTONDOWN: - rightMouseButton = 1; + // We changed semantic and react only on button up event break; case Common::EVENT_RBUTTONUP: - rightMouseButton = 0; + rightMouseButton = 1; break; case Common::EVENT_QUIT: // TODO @@ -758,11 +779,17 @@ void DrasculaEngine::updateEvents() { } void DrasculaEngine::delay(int ms) { - _system->delayMillis(ms * 2); // originally was 1 + uint32 end = _system->getMillis() + ms * 2; // originally was 1 + + do { + _system->delayMillis(10); + updateEvents(); + _system->updateScreen(); + } while (_system->getMillis() < end); } void DrasculaEngine::pause(int duration) { - _system->delayMillis(duration * 30); // was originally 2 + delay(duration * 15); } int DrasculaEngine::getTime() { diff --git a/engines/drascula/drascula.h b/engines/drascula/drascula.h index 4876cf3390..0a8b7c8c9b 100644 --- a/engines/drascula/drascula.h +++ b/engines/drascula/drascula.h @@ -317,6 +317,8 @@ static const int interf_y[] = { 51, 51, 51, 51, 83, 83, 83 }; struct RoomHandlers; +class Console; + class DrasculaEngine : public ::Engine { protected: // Engine APIs @@ -389,6 +391,7 @@ public: // Graphics buffers/pointers byte *bgSurface; byte *backSurface; + byte *cursorSurface; byte *drawSurface3; byte *drawSurface2; byte *tableSurface; @@ -733,6 +736,8 @@ public: private: int _lang; + Console *_console; + CharInfo *_charMap; int _charMapSize; diff --git a/engines/drascula/graphics.cpp b/engines/drascula/graphics.cpp index 00399816da..70085b99af 100644 --- a/engines/drascula/graphics.cpp +++ b/engines/drascula/graphics.cpp @@ -54,6 +54,7 @@ void DrasculaEngine::allocMemory() { assert(crosshairCursor); mouseCursor = (byte *)malloc(OBJWIDTH * OBJHEIGHT); assert(mouseCursor); + cursorSurface = (byte *)malloc(64000); } void DrasculaEngine::freeMemory() { @@ -67,6 +68,7 @@ void DrasculaEngine::freeMemory() { free(frontSurface); free(crosshairCursor); free(mouseCursor); + free(cursorSurface); } void DrasculaEngine::moveCursor() { @@ -90,6 +92,8 @@ void DrasculaEngine::moveCursor() { } void DrasculaEngine::loadPic(const char *NamePcc, byte *targetSurface, int colorCount) { + debug(5, "loadPic(%s)", NamePcc); + uint dataSize = 0; byte *pcxData; @@ -147,8 +151,7 @@ void DrasculaEngine::showFrame(Common::SeekableReadStream *stream, bool firstFra free(prevFrame); } -void DrasculaEngine::copyBackground(int xorg, int yorg, int xdes, int ydes, int width, - int height, byte *src, byte *dest) { +void DrasculaEngine::copyBackground(int xorg, int yorg, int xdes, int ydes, int width, int height, byte *src, byte *dest) { dest += xdes + ydes * 320; src += xorg + yorg * 320; /* Unoptimized code @@ -190,16 +193,20 @@ void DrasculaEngine::copyRect(int xorg, int yorg, int xdes, int ydes, int width, dest += xdes + ydes * 320; src += xorg + yorg * 320; - for (y = 0; y < height; y++) - for (x = 0; x < width; x++) - if (src[x + y * 320] != 255) - dest[x + y * 320] = src[x + y * 320]; + int ptr = 0; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + if (src[ptr] != 255) + dest[ptr] = src[ptr]; + ptr++; + } + ptr += 320 - width; + } + } void DrasculaEngine::updateScreen(int xorg, int yorg, int xdes, int ydes, int width, int height, byte *buffer) { - byte *screenBuffer = (byte *)_system->lockScreen()->pixels; - copyBackground(xorg, yorg, xdes, ydes, width, height, buffer, screenBuffer); - _system->unlockScreen(); + _system->copyRectToScreen(buffer + xorg + yorg * 320, 320, xdes, ydes, width, height); _system->updateScreen(); } diff --git a/engines/drascula/interface.cpp b/engines/drascula/interface.cpp index 21803a8932..1495694a1b 100644 --- a/engines/drascula/interface.cpp +++ b/engines/drascula/interface.cpp @@ -65,6 +65,8 @@ void DrasculaEngine::selectVerbFromBar() { } void DrasculaEngine::selectVerb(int verb) { + debug(4, "selectVerb(%d)", verb); + int c = _menuScreen ? 0 : 171; if (currentChapter == 5) { @@ -76,7 +78,7 @@ void DrasculaEngine::selectVerb(int verb) { } for (int i = 0; i < OBJHEIGHT; i++) - memcpy(mouseCursor + i * OBJWIDTH, backSurface + OBJWIDTH * verb + (c + i) * 320, OBJWIDTH); + memcpy(mouseCursor + i * OBJWIDTH, cursorSurface + OBJWIDTH * verb + (c + i) * 320, OBJWIDTH); setCursor(kCursorCurrentItem); if (verb > 0) { @@ -126,7 +128,7 @@ void DrasculaEngine::showMenu() { OBJWIDTH, OBJHEIGHT, srcSurface, screenSurface); } copyRect(_x1d_menu[h], _y1d_menu[h], _itemLocations[n].x, _itemLocations[n].y, - OBJWIDTH, OBJHEIGHT, backSurface, screenSurface); + OBJWIDTH, OBJHEIGHT, cursorSurface, screenSurface); } if (x < 7) @@ -140,7 +142,7 @@ void DrasculaEngine::clearMenu() { if (mouseX > _verbBarX[n] && mouseX < _verbBarX[n + 1]) verbActivated = 0; copyRect(OBJWIDTH * n, OBJHEIGHT * verbActivated, _verbBarX[n], 2, - OBJWIDTH, OBJHEIGHT, backSurface, screenSurface); + OBJWIDTH, OBJHEIGHT, cursorSurface, screenSurface); verbActivated = 1; } } diff --git a/engines/drascula/module.mk b/engines/drascula/module.mk index a9fa257549..20fd900124 100644 --- a/engines/drascula/module.mk +++ b/engines/drascula/module.mk @@ -3,6 +3,7 @@ MODULE := engines/drascula MODULE_OBJS := \ actors.o \ animation.o \ + console.o \ converse.o \ detection.o \ drascula.o \ diff --git a/engines/drascula/objects.cpp b/engines/drascula/objects.cpp index 13c8a742ca..73aea7b7f2 100644 --- a/engines/drascula/objects.cpp +++ b/engines/drascula/objects.cpp @@ -78,8 +78,11 @@ void DrasculaEngine::gotoObject(int pointX, int pointY) { for (;;) { updateRoom(); updateScreen(); + updateEvents(); if (characterMoved == 0) break; + + pause(3); } if (walkToObject == 1) { diff --git a/engines/drascula/palette.cpp b/engines/drascula/palette.cpp index 1e51deffd9..0f75bb7959 100644 --- a/engines/drascula/palette.cpp +++ b/engines/drascula/palette.cpp @@ -106,6 +106,8 @@ void DrasculaEngine::fadeToBlack(int fadeSpeed) { pause(fadeSpeed); setPalette((byte *)&palFade); + + updateEvents(); } } @@ -124,6 +126,8 @@ void DrasculaEngine::fadeFromBlack(int fadeSpeed) { pause(fadeSpeed); setPalette((byte *)&palFade); + + updateEvents(); } } diff --git a/engines/drascula/rooms.cpp b/engines/drascula/rooms.cpp index a71545feca..57bfad26af 100644 --- a/engines/drascula/rooms.cpp +++ b/engines/drascula/rooms.cpp @@ -1091,7 +1091,7 @@ void DrasculaEngine::updateRefresh() { sprintf(rm, "update_%d", roomNumber); for (uint i = 0; i < _roomHandlers->roomUpdaters.size(); i++) { if (!strcmp(rm, _roomHandlers->roomUpdaters[i]->desc)) { - debug(4, "Calling room updater %d", roomNumber); + debug(8, "Calling room updater %d", roomNumber); (this->*(_roomHandlers->roomUpdaters[i]->proc))(); break; } @@ -1129,7 +1129,7 @@ void DrasculaEngine::updateRefresh_pre() { sprintf(rm, "update_%d_pre", roomNumber); for (uint i = 0; i < _roomHandlers->roomPreupdaters.size(); i++) { if (!strcmp(rm, _roomHandlers->roomPreupdaters[i]->desc)) { - debug(4, "Calling room preupdater %d", roomNumber); + debug(8, "Calling room preupdater %d", roomNumber); (this->*(_roomHandlers->roomPreupdaters[i]->proc))(); break; } diff --git a/engines/drascula/talk.cpp b/engines/drascula/talk.cpp index 54175c5e5b..8cefe0385c 100644 --- a/engines/drascula/talk.cpp +++ b/engines/drascula/talk.cpp @@ -170,6 +170,7 @@ void DrasculaEngine::talk_drascula(int index, int talkerType) { centerText(said, drasculaX + 19, drasculaY); updateScreen(); + updateEvents(); pause(3); @@ -215,6 +216,7 @@ void DrasculaEngine::talk_drascula_big(int index) { centerText(said, 191, 69); updateScreen(); + updateEvents(); pause(3); @@ -245,7 +247,9 @@ void DrasculaEngine::talk_solo(const char *said, const char *filename) { else if (currentChapter == 5) centerText(said, 173, 92); } + updateEvents(); updateScreen(); + pause(3); } while (!isTalkFinished()); if (currentChapter == 6) { @@ -304,6 +308,7 @@ void DrasculaEngine::talk_bartender(int index, int talkerType) { centerText(said, 132, 45); updateScreen(); + updateEvents(); pause(3); } while (!isTalkFinished()); @@ -331,11 +336,9 @@ void DrasculaEngine::talk_bj(int index) { updateRefresh_pre(); - copyBackground(bjX + 2, bjY - 1, bjX + 2, bjY - 1, 27, 40, - bgSurface, screenSurface); + copyBackground(bjX + 2, bjY - 1, bjX + 2, bjY - 1, 27, 40, bgSurface, screenSurface); - copyRect(x_talk[face], 99, bjX + 2, bjY - 1, 27, 40, - drawSurface3, screenSurface); + copyRect(x_talk[face], 99, bjX + 2, bjY - 1, 27, 40, drawSurface3, screenSurface); moveCharacters(); updateRefresh(); @@ -353,6 +356,7 @@ void DrasculaEngine::talk_bj(int index) { updateScreen(); } + updateEvents(); } while (!isTalkFinished()); updateRoom(); @@ -467,6 +471,7 @@ void DrasculaEngine::talk(const char *said, const char *filename) { centerText(said, curX, curY); updateScreen(); + updateEvents(); pause(3); } while (!isTalkFinished()); @@ -558,16 +563,15 @@ void DrasculaEngine::talk_vonBraun(int index, int talkerType) { if (!_subtitlesDisabled) centerText(said, vonBraunX, 66); - updateScreen(); - pause(3); } else { updateRoom(); if (!_subtitlesDisabled) centerText(said, 150, 80); - - updateScreen(); } + updateScreen(); + updateEvents(); + pause(3); } while (!isTalkFinished()); updateRoom(); @@ -621,6 +625,7 @@ void DrasculaEngine::talk_blind(int index) { centerText(said, 260, 71); updateScreen(); + updateEvents(); pause(2); p++; } while (!isTalkFinished()); @@ -641,7 +646,9 @@ void DrasculaEngine::talk_hacker(int index) { do { if (!_subtitlesDisabled) centerText(said, 156, 170); + updateEvents(); updateScreen(); + pause(3); } while (!isTalkFinished()); } @@ -693,13 +700,13 @@ void DrasculaEngine::talk_pen(const char *said, const char *filename, int talker copyBackground(); updateRefresh_pre(); + updateRefresh(); + if (talkerType == 0) copyRect(x_talk[face], 145, 145, 105, 25, 29, drawSurface3, screenSurface); else copyBackground(x_talk2[face], 171, 173, 116, 25, 28, drawSurface3, screenSurface); - updateRefresh(); - if (!_subtitlesDisabled) { if (talkerType == 0) centerText(said, 160, 105); @@ -708,6 +715,7 @@ void DrasculaEngine::talk_pen(const char *said, const char *filename, int talker } updateScreen(); + updateEvents(); pause(3); } while (!isTalkFinished()); @@ -745,6 +753,7 @@ void DrasculaEngine::talk_bj_bed(int index) { centerText(said, 104, 102); updateScreen(); + updateEvents(); pause(3); } while (!isTalkFinished()); @@ -781,6 +790,7 @@ void DrasculaEngine::talk_htel(int index) { centerText(said, 90, 50); updateScreen(); + updateEvents(); pause(3); } while (!isTalkFinished()); @@ -862,6 +872,7 @@ void DrasculaEngine::talk_sync(const char *said, const char *filename, const cha centerText(said, curX, curY); updateScreen(); + updateEvents(); p++; pause(3); @@ -895,6 +906,7 @@ void DrasculaEngine::talk_trunk(int index) { centerText(said, 263, 69); updateScreen(); + updateEvents(); pause(4); } while (!isTalkFinished()); @@ -922,6 +934,7 @@ void DrasculaEngine::talk_generic(const char* said, const char* filename, int* f centerText(said, coords[5], coords[6]); updateScreen(); + updateEvents(); pause(3); } while (!isTalkFinished()); @@ -944,8 +957,10 @@ void DrasculaEngine::grr() { updateScreen(); - while (!isTalkFinished()) - ; + while (!isTalkFinished()) { + updateEvents(); + pause(3); + } updateRoom(); updateScreen(); diff --git a/engines/engine.cpp b/engines/engine.cpp index 0f42cd493d..84fc0bbe4e 100644 --- a/engines/engine.cpp +++ b/engines/engine.cpp @@ -23,6 +23,7 @@ */ #if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) +#define WIN32_LEAN_AND_MEAN #include <windows.h> #include <direct.h> // winnt.h defines ARRAYSIZE, but we want our own one... diff --git a/engines/game.cpp b/engines/game.cpp index c7f26019d6..dea6d37485 100644 --- a/engines/game.cpp +++ b/engines/game.cpp @@ -73,6 +73,10 @@ void GameDescriptor::setGUIOptions(uint32 guioptions) { erase("guioptions"); } +void GameDescriptor::appendGUIOptions(const Common::String &str) { + setVal("guioptions", getVal("guioptions", "") + " " + str); +} + void GameDescriptor::updateDesc(const char *extra) { // TODO: The format used here (LANG/PLATFORM/EXTRA) is not set in stone. // We may want to change the order (PLATFORM/EXTRA/LANG, anybody?), or diff --git a/engines/game.h b/engines/game.h index 49136ecf5a..b125421ff6 100644 --- a/engines/game.h +++ b/engines/game.h @@ -83,6 +83,7 @@ public: void updateDesc(const char *extra = 0); void setGUIOptions(uint32 options); + void appendGUIOptions(const Common::String &str); Common::String &gameid() { return getVal("gameid"); } Common::String &description() { return getVal("description"); } diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp index 1f8bfdc138..a1eb8055aa 100644 --- a/engines/gob/detection.cpp +++ b/engines/gob/detection.cpp @@ -87,4994 +87,7 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = { {0, 0, kPlatformUnknown} }; -namespace Gob { - -using Common::GUIO_NOSPEECH; -using Common::GUIO_NOSUBTITLES; -using Common::GUIO_NONE; - -static const GOBGameDescription gameDescriptions[] = { - { // Supplied by Florian Zeitz on scummvm-devel - { - "gob1", - "EGA", - AD_ENTRY1("intro.stk", "c65e9cc8ba23a38456242e1f2b1caad4"), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesEGA, - 0, 0, 0 - }, - { - { - "gob1", - "EGA", - AD_ENTRY1("intro.stk", "f9233283a0be2464248d83e14b95f09c"), - RU_RUS, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesEGA, - 0, 0, 0 - }, - { // Supplied by Theruler76 in bug report #1201233 - { - "gob1", - "VGA", - AD_ENTRY1("intro.stk", "26a9118c0770fa5ac93a9626761600b2"), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by raziel_ in bug report #1891864 - { - "gob1", - "VGA", - AD_ENTRY1s("intro.stk", "e157cb59c6d330ca70d12ab0ef1dd12b", 288972), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by raina in the forums - { - "gob1", - "", - AD_ENTRY1s("intro.stk", "6d837c6380d8f4d984c9f6cc0026df4f", 192712), - EN_ANY, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by paul66 in bug report #1652352 - { - "gob1", - "", - AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), - EN_ANY, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by paul66 in bug report #1652352 - { - "gob1", - "", - AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), - DE_DEU, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by paul66 in bug report #1652352 - { - "gob1", - "", - AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), - FR_FRA, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by paul66 in bug report #1652352 - { - "gob1", - "", - AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), - IT_ITA, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by paul66 in bug report #1652352 - { - "gob1", - "", - AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), - ES_ESP, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by Hkz on #scummvm - { - "gob1", - "", - { - {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by Hkz on #scummvm - { - "gob1", - "", - { - {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - IT_ITA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by Hkz on #scummvm - { - "gob1", - "", - { - {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - EN_GRB, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by Hkz on #scummvm - { - "gob1", - "", - { - {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - DE_DEU, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by Hkz on #scummvm - { - "gob1", - "", - { - {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - ES_ESP, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob1", - "", - { - {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - EN_GRB, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob1", - "", - { - {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob1", - "", - { - {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - ES_ESP, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob1", - "", - { - {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - IT_ITA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob1", - "", - { - {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - DE_DEU, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Found in Found in french ADI 2.5 Anglais Multimedia 5e - { - "gob1", - "", - AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Found in Found in french ADI 2.5 Anglais Multimedia 5e - { - "gob1", - "", - AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), - EN_GRB, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Found in Found in french ADI 2.5 Anglais Multimedia 5e - { - "gob1", - "", - AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), - DE_DEU, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Found in Found in french ADI 2.5 Anglais Multimedia 5e - { - "gob1", - "", - AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), - IT_ITA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Found in Found in french ADI 2.5 Anglais Multimedia 5e - { - "gob1", - "", - AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), - ES_ESP, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // CD 1.000 version. - { - "gob1cd", - "v1.000", - AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // CD 1.000 version. - { - "gob1cd", - "v1.000", - AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // CD 1.000 version. - { - "gob1cd", - "v1.000", - AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // CD 1.000 version. - { - "gob1cd", - "v1.000", - AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // CD 1.000 version. - { - "gob1cd", - "v1.000", - AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // CD 1.02 version. Multilingual - { - "gob1cd", - "v1.02", - AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // CD 1.02 version. Multilingual - { - "gob1cd", - "v1.02", - AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // CD 1.02 version. Multilingual - { - "gob1cd", - "v1.02", - AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // CD 1.02 version. Multilingual - { - "gob1cd", - "v1.02", - AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // CD 1.02 version. Multilingual - { - "gob1cd", - "v1.02", - AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob1cd", - "v1.02", - AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), - HU_HUN, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob1cd", - "v1.02", - AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob1cd", - "v1.02", - AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob1cd", - "v1.02", - AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "gob1", - "Demo", - AD_ENTRY1("intro.stk", "972f22c6ff8144a6636423f0354ca549"), - UNK_LANG, - kPlatformAmiga, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "gob1", - "Interactive Demo", - AD_ENTRY1("intro.stk", "e72bd1e3828c7dec4c8a3e58c48bdfdb"), - UNK_LANG, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "gob1", - "Interactive Demo", - AD_ENTRY1s("intro.stk", "a796096280d5efd48cf8e7dfbe426eb5", 193595), - UNK_LANG, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2785958 - { - "gob1", - "Interactive Demo", - AD_ENTRY1s("intro.stk", "35a098571af9a03c04e2303aec7c9249", 116582), - FR_FRA, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "gob1", - "", - AD_ENTRY1s("intro.stk", "0e022d3f2481b39e9175d37b2c6ad4c6", 2390121), - FR_FRA, - kPlatformCDi, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, "AVT003.TOT", 0 - }, - { // Supplied by fac76 in bug report #1883808 - { - "gob2", - "", - AD_ENTRY1s("intro.stk", "eebf2810122cfd17399260cd1468e994", 554014), - EN_ANY, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "gob2", - "", - AD_ENTRY1("intro.stk", "d28b9e9b41f31acfa58dcd12406c7b2c"), - DE_DEU, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2602057 - { - "gob2", - "", - AD_ENTRY1("intro.stk", "686c88f7302a80b744aae9f8413e853d"), - IT_ITA, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by bgk in bug report #1706861 - { - "gob2", - "", - AD_ENTRY1s("intro.stk", "4b13c02d1069b86bcfec80f4e474b98b", 554680), - FR_FRA, - kPlatformAtariST, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by fac76 in bug report #1673397 - { - "gob2", - "", - { - {"intro.stk", 0, "b45b984ee8017efd6ea965b9becd4d66", 828443}, - {"musmac1.mid", 0, "7f96f491448c7a001b32df89cf8d2af2", 1658}, - {0, 0, 0, 0} - }, - UNK_LANG, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by koalet in bug report #2478585 - { - "gob2", - "", - { - {"intro.stk", 0, "a13ecb4f6d8fd881ebbcc02e45cb5475", 837275}, - {"musmac1.mid", 0, "7f96f491448c7a001b32df89cf8d2af2", 1658}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - AD_ENTRY1("intro.stk", "b45b984ee8017efd6ea965b9becd4d66"), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - AD_ENTRY1("intro.stk", "dedb5d31d8c8050a8cf77abedcc53dae"), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by raziel_ in bug report #1891867 - { - "gob2", - "", - AD_ENTRY1s("intro.stk", "25a99827cd59751a80bed9620fb677a0", 893302), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - AD_ENTRY1s("intro.stk", "a13ecb4f6d8fd881ebbcc02e45cb5475", 837275), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by blackwhiteeagle in bug report #1605235 - { - "gob2", - "", - AD_ENTRY1("intro.stk", "3e4e7db0d201587dd2df4003b2993ef6"), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - AD_ENTRY1("intro.stk", "a13892cdf4badda85a6f6fb47603a128"), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2602017 - { - "gob2", - "", - AD_ENTRY1("intro.stk", "c47faf1d406504e6ffe63243610bb1f4"), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - AD_ENTRY1("intro.stk", "cd3e1df8b273636ee32e34b7064f50e8"), - RU_RUS, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by arcepi in bug report #1659884 - { - "gob2", - "", - AD_ENTRY1s("intro.stk", "5f53c56e3aa2f1e76c2e4f0caa15887f", 829232), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - { - {"intro.stk", 0, "285d7340f98ebad65d465585da12910b", 837286}, - {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - { - {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302}, - {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, - {0, 0, 0, 0} - }, - EN_USA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - { - {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302}, - {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - { - {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302}, - {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, - {0, 0, 0, 0} - }, - DE_DEU, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - { - {"intro.stk", 0, "6efac0a14c0de4d57dde8592456c8acf", 845172}, - {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, - {0, 0, 0, 0} - }, - EN_USA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - { - {"intro.stk", 0, "6efac0a14c0de4d57dde8592456c8acf", 845172}, - {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Found in french ADI 2 Francais-Maths CM1 - { - "gob2", - "", - AD_ENTRY1s("intro.stk", "24489330a1d67ff978211f574822a5a6", 883756), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Found in french ADI 2.5 Anglais Multimedia 5e - { - "gob2", - "", - AD_ENTRY1s("intro.stk", "285d7340f98ebad65d465585da12910b", 837286), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2cd", - "v1.000", - AD_ENTRY1("intro.stk", "9de5fbb41cf97182109e5fecc9d90347"), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "gob2cd", - "v2.01", - AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "gob2cd", - "v2.01", - AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "gob2cd", - "v2.01", - AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "gob2cd", - "v2.01", - AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "gob2cd", - "v2.01", - AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob2cd", - "v1.02", - AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), - HU_HUN, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob2cd", - "v1.02", - AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob2cd", - "v1.02", - AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob2cd", - "v1.02", - AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob2cd", - "v1.02", - AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "gob2", - "Non-Interactive Demo", - AD_ENTRY1("intro.stk", "8b1c98ff2ab2e14f47a1b891e9b92217"), - UNK_LANG, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, "usa.tot", 0 - }, - { - { - "gob2", - "Interactive Demo", - AD_ENTRY1("intro.stk", "cf1c95b2939bd8ff58a25c756cb6125e"), - UNK_LANG, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "Interactive Demo", - AD_ENTRY1("intro.stk", "4b278c2678ea01383fd5ca114d947eea"), - UNK_LANG, - kPlatformAmiga, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by polluks in bug report #1895126 - { - "gob2", - "Interactive Demo", - AD_ENTRY1s("intro.stk", "9fa85aea959fa8c582085855fbd99346", 553063), - UNK_LANG, - kPlatformAmiga, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by vampir_raziel in bug report #1658373 - { - "ween", - "", - { - {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570}, - {"ween.ins", 0, "d2cb24292c9ddafcad07e23382027218", 87800}, - {0, 0, 0, 0} - }, - EN_GRB, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by vampir_raziel in bug report #1658373 - { - "ween", - "", - AD_ENTRY1s("intro.stk", "257fe669705ac4971efdfd5656eef16a", 457719), - FR_FRA, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by vampir_raziel in bug report #1658373 - { - "ween", - "", - AD_ENTRY1s("intro.stk", "dffd1ab98fe76150d6933329ca6f4cc4", 459458), - FR_FRA, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by vampir_raziel in bug report #1658373 - { - "ween", - "", - AD_ENTRY1s("intro.stk", "af83debf2cbea21faa591c7b4608fe92", 458192), - DE_DEU, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2563539 - { - "ween", - "", - { - {"intro.stk", 0, "dffd1ab98fe76150d6933329ca6f4cc4", 459458}, - {"ween.ins", 0, "d2cb24292c9ddafcad07e23382027218", 87800}, - {0, 0, 0, 0} - }, - IT_ITA, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by pwigren in bug report #1764174 - { - "ween", - "", - { - {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570}, - {"music__5.snd", 0, "7d1819b9981ecddd53d3aacbc75f1cc8", 13446}, - {0, 0, 0, 0} - }, - EN_GRB, - kPlatformAtariST, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "ween", - "", - AD_ENTRY1("intro.stk", "e6d13fb3b858cb4f78a8780d184d5b2c"), - FR_FRA, - kPlatformAtariST, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "ween", - "", - AD_ENTRY1("intro.stk", "2bb8878a8042244dd2b96ff682381baa"), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "ween", - "", - AD_ENTRY1s("intro.stk", "de92e5c6a8c163007ffceebef6e67f7d", 7117568), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by cybot_tmin in bug report #1667743 - { - "ween", - "", - AD_ENTRY1s("intro.stk", "6d60f9205ecfbd8735da2ee7823a70dc", 7014426), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "ween", - "", - AD_ENTRY1("intro.stk", "4b10525a3782aa7ecd9d833b5c1d308b"), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by cartman_ on #scummvm - { - "ween", - "", - AD_ENTRY1("intro.stk", "63170e71f04faba88673b3f510f9c4c8"), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by glorfindel in bugreport #1722142 - { - "ween", - "", - AD_ENTRY1s("intro.stk", "8b57cd510da8a3bbd99e3a0297a8ebd1", 7018771), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "ween", - "Demo", - AD_ENTRY1("intro.stk", "2e9c2898f6bf206ede801e3b2e7ee428"), - UNK_LANG, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesAdLib, - 0, "show.tot", 0 - }, - { - { - "ween", - "Demo", - AD_ENTRY1("intro.stk", "15fb91a1b9b09684b28ac75edf66e504"), - EN_USA, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesAdLib, - 0, "show.tot", 0 - }, - { - { - "bargon", - "", - AD_ENTRY1("intro.stk", "da3c54be18ab73fbdb32db24624a9c23"), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBargon, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by Trekky in the forums - { - "bargon", - "", - AD_ENTRY1s("intro.stk", "2f54b330d21f65b04b7c1f8cca76426c", 262109), - FR_FRA, - kPlatformAtariST, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBargon, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by cesardark in bug #1681649 - { - "bargon", - "", - AD_ENTRY1s("intro.stk", "11103b304286c23945560b391fd37e7d", 3181890), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBargon, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by paul66 in bug #1692667 - { - "bargon", - "", - AD_ENTRY1s("intro.stk", "da3c54be18ab73fbdb32db24624a9c23", 3181825), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBargon, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by pwigren in bugreport #1764174 - { - "bargon", - "", - AD_ENTRY1s("intro.stk", "569d679fe41d49972d34c9fce5930dda", 269825), - EN_ANY, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBargon, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by kizkoool in bugreport #2089734 - { - "bargon", - "", - AD_ENTRY1s("intro.stk", "00f6b4e2ee26e5c40b488e2df5adcf03", 3975580), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBargon, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by glorfindel in bugreport #1722142 - { - "bargon", - "Fanmade", - AD_ENTRY1s("intro.stk", "da3c54be18ab73fbdb32db24624a9c23", 3181825), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBargon, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "littlered", - "", - { - {"intro.stk", 0, "0b72992f5d8b5e6e0330572a5753ea25", 256490}, - {"mod.babayaga", 0, "43484cde74e0860785f8e19f0bc776d1", 60248}, - {0, 0, 0, 0} - }, - UNK_LANG, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), - EN_GRB, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), - DE_DEU, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), - IT_ITA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), - ES_ESP, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { // Found in french ADI 2 Francais-Maths CM1 - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { // Found in french ADI 2 Francais-Maths CM1 - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), - ES_ESP, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { // Found in french ADI 2 Francais-Maths CM1 - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), - EN_GRB, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { // Found in french ADI 2 Francais-Maths CM1 - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), - IT_ITA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { // Found in french ADI 2 Francais-Maths CM1 - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), - DE_DEU, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "7b7f48490dedc8a7cb999388e2fadbe3", 3930674), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "e0767783ff662ed93665446665693aef", 4371238), - HE_ISR, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by cartman_ on #scummvm - { - "lit", - "", - AD_ENTRY1s("intro.stk", "f1f78b663893b58887add182a77df151", 3944090), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2105220 - { - "lit", - "", - AD_ENTRY1s("intro.stk", "cd322cb3c64ef2ba2f2134aa2122cfe9", 3936700), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by koalet in bug report #2479034 - { - "lit", - "", - { - {"intro.stk", 0, "af98bcdc70e1f1c1635577fd726fe7f1", 3937310}, - {"musmac1.mid", 0, "ae7229bb09c6abe4e60a2768b24bc890", 9398}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by SiRoCs in bug report #2093672 - { - "lit", - "", - AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by SiRoCs in bug report #2093672 - { - "lit", - "", - AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by SiRoCs in bug report #2093672 - { - "lit", - "", - AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by SiRoCs in bug report #2093672 - { - "lit", - "", - AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by SiRoCs in bug report #2093672 - { - "lit", - "", - AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by SiRoCs in bug report #2093672 - { - "lit", - "", - AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330), - EN_GRB, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330), - ES_ESP, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4219382), - DE_DEU, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4219382), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Found in french ADI 2.6 Francais-Maths 4e - { - "lit", - "", - AD_ENTRY1s("intro.stk", "58ee9583a4fb837f02d9a58e5f442656", 3937120), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit1", - "Full install", - { - {"intro.stk", 0, "93c91bc9e783d00033042ae83144d7dd", 72318}, - {"partie2.itk", 0, "78f00bd8eb9e680e6289bba0130b1b33", 4396644}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit1", - "Light install", - { - {"intro.stk", 0, "93c91bc9e783d00033042ae83144d7dd", 72318}, - {"partie2.itk", 0, "78f00bd8eb9e680e6289bba0130b1b33", 664064}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit2", - "Light install", - AD_ENTRY1s("intro.stk", "17acbb212e62addbe48dc8f2282c98cb", 72318), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit2", - "Full install", - { - {"intro.stk", 0, "17acbb212e62addbe48dc8f2282c98cb", 72318}, - {"partie4.itk", 0, "6ce4967e0c79d7daeabc6c1d26783d4c", 2612087}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit", - "Demo", - AD_ENTRY1("demo.stk", "c06f8cc20eb239d4c71f225ce3093edf"), - UNK_LANG, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - "demo.stk", "demo.tot", 0 - }, - { - { - "lit", - "Non-interactive Demo", - AD_ENTRY1("demo.stk", "2eba8abd9e3878c57307576012dd2fec"), - UNK_LANG, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - "demo.stk", "demo.tot", 0 - }, - { - { - "fascination", - "CD Version (Censored)", - AD_ENTRY1s("disk0.stk", "9c61e9c22077f72921f07153e37ccf01", 545953), - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES - }, - kGameTypeFascination, - kFeaturesCD, - "disk0.stk", 0, 0 - }, - { - { - "fascination", - "VGA 3 disks edition", - AD_ENTRY1s("disk0.stk", "a50a8495e1b2d67699fb562cb98fc3e2", 1064387), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesAdLib, - "disk0.stk", 0, 0 - }, - { - { - "fascination", - "VGA 3 disks edition", - AD_ENTRY1s("intro.stk", "d6e45ce548598727e2b5587a99718eba", 1055909), - HE_ISR, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesAdLib, - "intro.stk", 0, 0 - }, - { // Supplied by sanguine - { - "fascination", - "VGA 3 disks edition", - AD_ENTRY1s("disk0.stk", "c14330d052fe4da5a441ac9d81bc5891", 1061955), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesAdLib, - "disk0.stk", 0, 0 - }, - { // Supplied by windlepoons in bug report #2809247 - { - "fascination", - "VGA 3 disks edition", - AD_ENTRY1s("disk0.stk", "3a24e60a035250189643c86a9ceafb97", 1062480), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesAdLib, - "disk0.stk", 0, 0 - }, - { - { - "fascination", - "VGA", - AD_ENTRY1s("disk0.stk", "e8ab4f200a2304849f462dc901705599", 183337), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesAdLib, - "disk0.stk", 0, 0 - }, - { - { - "fascination", - "", - AD_ENTRY1s("disk0.stk", "68b1c01564f774c0b640075fbad1b695", 189968), - DE_DEU, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesNone, - "disk0.stk", 0, 0 - }, - { - { - "fascination", - "", - AD_ENTRY1s("disk0.stk", "7062117e9c5adfb6bfb2dac3ff74df9e", 189951), - EN_ANY, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesNone, - "disk0.stk", 0, 0 - }, - { - { - "fascination", - "", - AD_ENTRY1s("disk0.stk", "55c154e5a3e8e98afebdcff4b522e1eb", 190005), - FR_FRA, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesNone, - "disk0.stk", 0, 0 - }, - { - { - "fascination", - "", - AD_ENTRY1s("disk0.stk", "7691827fff35df7799f14cfd6be178ad", 189931), - IT_ITA, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesNone, - "disk0.stk", 0, 0 - }, - { - { - "fascination", - "", - AD_ENTRY1s("disk0.stk", "aff9fcc619f4dd19eae228affd0d34c8", 189964), - EN_ANY, - kPlatformAtariST, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesNone, - "disk0.stk", 0, 0 - }, - { - { - "geisha", - "", - AD_ENTRY1s("disk1.stk", "6eebbb98ad90cd3c44549fc2ab30f632", 212153), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGeisha, - kFeaturesNone, - "disk1.stk", "intro.tot", 0 - }, - { - { - "geisha", - "", - AD_ENTRY1s("disk1.stk", "f4d4d9d20f7ad1f879fc417d47faba89", 336732), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGeisha, - kFeaturesNone, - "disk1.stk", "intro.tot", 0 - }, - { - { - "gob3", - "", - AD_ENTRY1s("intro.stk", "32b0f57f5ae79a9ae97e8011df38af42", 157084), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - AD_ENTRY1s("intro.stk", "904fc32032295baa3efb3a41f17db611", 178582), - HE_ISR, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by raziel_ in bug report #1891869 - { - "gob3", - "", - AD_ENTRY1s("intro.stk", "16b014bf32dbd6ab4c5163c44f56fed1", 445104), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - { - {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104}, - {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, - {0, 0, 0, 0} - }, - DE_DEU, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - { - {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104}, - {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - { - {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104}, - {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, - {0, 0, 0, 0} - }, - EN_GRB, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by fac76 in bug report #1742716 - { - "gob3", - "", - { - {"intro.stk", 0, "32b0f57f5ae79a9ae97e8011df38af42", 157084}, - {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, - {0, 0, 0, 0} - }, - EN_GRB, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - AD_ENTRY1("intro.stk", "1e2f64ec8dfa89f42ee49936a27e66e7"), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by paul66 in bug report #1652352 - { - "gob3", - "", - AD_ENTRY1("intro.stk", "f6d225b25a180606fa5dbe6405c97380"), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - AD_ENTRY1("intro.stk", "e42a4f2337d6549487a80864d7826972"), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by Paranoimia on #scummvm - { - "gob3", - "", - AD_ENTRY1s("intro.stk", "fe8144daece35538085adb59c2d29613", 159402), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - AD_ENTRY1("intro.stk", "4e3af248a48a2321364736afab868527"), - RU_RUS, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - AD_ENTRY1("intro.stk", "8d28ce1591b0e9cc79bf41cad0fc4c9c"), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by SiRoCs in bug report #2098621 - { - "gob3", - "", - AD_ENTRY1s("intro.stk", "d3b72938fbbc8159198088811f9e6d19", 160382), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - AD_ENTRY1("intro.stk", "bd679eafde2084d8011f247e51b5a805"), - EN_GRB, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesNone, - 0, "menu.tot", 0 - }, - { - { - "gob3", - "", - AD_ENTRY1("intro.stk", "bd679eafde2084d8011f247e51b5a805"), - DE_DEU, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesNone, - 0, "menu.tot", 0 - }, - { - { - "gob3", - "", - { - {"intro.stk", 0, "edd7403e5dc2a14459d2665a4c17714d", 209534}, - {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - { - {"intro.stk", 0, "428e2de130cf3b303c938924539dc50d", 324420}, - {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - { - {"intro.stk", 0, "428e2de130cf3b303c938924539dc50d", 324420}, - {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Found in Found in french ADI 2.5 Anglais Multimedia 5e - { - "gob3", - "", - AD_ENTRY1s("intro.stk", "edd7403e5dc2a14459d2665a4c17714d", 209534), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3cd", - "v1.000", - AD_ENTRY1("intro.stk", "6f2c226c62dd7ab0ab6f850e89d3fc47"), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 - { - "gob3cd", - "v1.02", - AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 - { - "gob3cd", - "v1.02", - AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 - { - "gob3cd", - "v1.02", - AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 - { - "gob3cd", - "v1.02", - AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 - { - "gob3cd", - "v1.02", - AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob3cd", - "v1.02", - AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), - HU_HUN, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob3cd", - "v1.02", - AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob3cd", - "v1.02", - AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob3cd", - "v1.02", - AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "gob3", - "Interactive Demo", - AD_ENTRY1("intro.stk", "7aebd94e49c2c5c518c9e7b74f25de9d"), - FR_FRA, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "Interactive Demo 2", - AD_ENTRY1("intro.stk", "e5dcbc9f6658ebb1e8fe26bc4da0806d"), - FR_FRA, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "Interactive Demo 3", - AD_ENTRY1s("intro.stk", "9e20ad7b471b01f84db526da34eaf0a2", 395561), - EN_ANY, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "Non-interactive Demo", - AD_ENTRY1("intro.stk", "b9b898fccebe02b69c086052d5024a55"), - UNK_LANG, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), - EN_USA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), - DE_DEU, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), - IT_ITA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), - ES_ESP, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "inca2", - "Non-Interactive Demo", - { - {"cons.imd", 0, "f896ba0c4a1ac7f7260d342655980b49", 17804}, - {"conseil.imd", 0, "aaedd5482d5b271e233e86c5a03cf62e", 33999}, - {"int.imd", 0, "6308222fcefbcb20925f01c1aff70dee", 30871}, - {"inter.imd", 0, "39bd6d3540f3bedcc97293f352c7f3fc", 191719}, - {"machu.imd", 0, "c0bc8211d93b467bfd063b63fe61b85c", 34609}, - {"post.imd", 0, "d75cad0e3fc22cb0c8b6faf597f509b2", 1047709}, - {"posta.imd", 0, "2a5b3fe75681ddf4d21ac724db8111b4", 547250}, - {"postb.imd", 0, "24260ce4e80a4c472352b76637265d09", 868312}, - {"postc.imd", 0, "24accbcc8b83a9c2be4bd82849a2bd29", 415637}, - {"tum.imd", 0, "0993d4810ec9deb3f77c5e92095320fd", 20330}, - {"tumi.imd", 0, "bf53f229480d694de0947fe3366fbec6", 248952}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesAdLib | kFeaturesBATDemo, - 0, 0, 7 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "5f5f4e0a72c33391e67a47674b120cc6", 20296422), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by jvprat on #scummvm - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by jvprat on #scummvm - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by jvprat on #scummvm - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by jvprat on #scummvm - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by jvprat on #scummvm - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by Hkz on #scummvm - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by Hkz on #scummvm - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by Hkz on #scummvm - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by DjDiabolik in bug report #1971294 - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by DjDiabolik in bug report #1971294 - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by DjDiabolik in bug report #1971294 - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by DjDiabolik in bug report #1971294 - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by DjDiabolik in bug report #1971294 - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2098838 - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "08a96bf061af1fa4f75c6a7cc56b60a4", 20734979), - PL_POL, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "Non-Interactive Demo", - { - {"demo.scn", 0, "16bb85fc5f8e519147b60475dbf33962", 89}, - {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640 | kFeaturesSCNDemo, - 0, 0, 1 - }, - { - { - "dynasty", - "", - AD_ENTRY1s("intro.stk", "6190e32404b672f4bbbc39cf76f41fda", 2511470), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeDynasty, - kFeatures640, - 0, 0, 0 - }, - { - { - "dynasty", - "", - AD_ENTRY1s("intro.stk", "61e4069c16e27775a6cc6d20f529fb36", 2511300), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeDynasty, - kFeatures640, - 0, 0, 0 - }, - { - { - "dynasty", - "", - AD_ENTRY1s("intro.stk", "61e4069c16e27775a6cc6d20f529fb36", 2511300), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeDynasty, - kFeatures640, - 0, 0, 0 - }, - { - { - "dynasty", - "", - AD_ENTRY1s("intro.stk", "b3f8472484b7a1df94557b51e7b6fca0", 2322644), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeDynasty, - kFeatures640, - 0, 0, 0 - }, - { - { - "dynasty", - "", - AD_ENTRY1s("intro.stk", "bdbdac8919200a5e71ffb9fb0709f704", 2446652), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeDynasty, - kFeatures640, - 0, 0, 0 - }, - { - { - "dynasty", - "Demo", - AD_ENTRY1s("intro.stk", "464538a17ed39755d7f1ba9c751af1bd", 1847864), - EN_USA, - kPlatformPC, - ADGF_DEMO, - GUIO_NONE - }, - kGameTypeDynasty, - kFeatures640, - 0, 0, 0 - }, - { - { - "dynasty", - "Demo", - AD_ENTRY1s("lda1.stk", "0e56a899357cbc0bf503260fd2dd634e", 15032774), - UNK_LANG, - kPlatformWindows, - ADGF_DEMO, - GUIO_NONE - }, - kGameTypeDynasty, - kFeatures640, - "lda1.stk", 0, 0 - }, - { - { - "dynasty", - "Demo", - AD_ENTRY1s("lda1.stk", "8669ea2e9a8239c070dc73958fbc8753", 15567724), - DE_DEU, - kPlatformWindows, - ADGF_DEMO, - GUIO_NONE - }, - kGameTypeDynasty, - kFeatures640, - "lda1.stk", 0, 0 - }, - { - { - "urban", - "", - AD_ENTRY1s("intro.stk", "3ab2c542bd9216ae5d02cc6f45701ae1", 1252436), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeUrban, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by gamin in the forums - { - "urban", - "", - AD_ENTRY1s("intro.stk", "b991ed1d31c793e560edefdb349882ef", 1276408), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeUrban, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by jvprat on #scummvm - { - "urban", - "", - AD_ENTRY1s("intro.stk", "4ec3c0864e2b54c5b4ccf9f6ad96528d", 1253328), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeUrban, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2770340 - { - "urban", - "", - AD_ENTRY1s("intro.stk", "4bd31979ea3d77a58a358c09000a85ed", 1253018), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeUrban, - kFeatures640, - 0, 0, 0 - }, - { - { - "urban", - "Non-Interactive Demo", - { - {"wdemo.s24", 0, "14ac9bd51db7a075d69ddb144904b271", 87}, - {"demo.vmd", 0, "65d04715d871c292518b56dd160b0161", 9091237}, - {"urband.vmd", 0, "60343891868c91854dd5c82766c70ecc", 922461}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeUrban, - kFeatures640 | kFeaturesSCNDemo, - 0, 0, 2 - }, - { - { - "playtoons1", - "", - { - {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338}, - {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons1", - "Pack mes histoires anim\xE9""es", - { - {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, - {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons1", - "", - { - {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, - {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674}, - {0, 0, 0, 0} - }, - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { // Supplied by scoriae in the forums - { - "playtoons1", - "", - { - {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, - {"archi.stk", 0, "00d8274519dfcf8a0d8ae3099daea0f8", 5532135}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons1", - "Non-Interactive Demo", - { - {"play123.scn", 0, "4689a31f543915e488c3bc46ea358add", 258}, - {"archi.vmd", 0, "a410fcc8116bc173f038100f5857191c", 5617210}, - {"chato.vmd", 0, "5a10e39cb66c396f2f9d8fb35e9ac016", 5445937}, - {"genedeb.vmd", 0, "3bb4a45585f88f4d839efdda6a1b582b", 1244228}, - {"generik.vmd", 0, "b46bdd64b063e86927fb2826500ad512", 603242}, - {"genespi.vmd", 0, "b7611916f32a370ae9832962fc17ef72", 758719}, - {"spirou.vmd", 0, "8513dbf7ac51c057b21d371d6b217b47", 2550788}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640 | kFeaturesSCNDemo, - 0, 0, 3 - }, - { - { - "playtoons1", - "Non-Interactive Demo", - { - {"e.scn", 0, "8a0db733c3f77be86e74e8242e5caa61", 124}, - {"demarchg.vmd", 0, "d14a95da7d8792faf5503f649ffcbc12", 5619415}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640 | kFeaturesSCNDemo, - 0, 0, 4 - }, - { - { - "playtoons1", - "Non-Interactive Demo", - { - {"i.scn", 0, "8b3294474d39970463663edd22341730", 285}, - {"demarita.vmd", 0, "84c8672b91c7312462603446e224bfec", 5742533}, - {"dembouit.vmd", 0, "7a5fdf0a4dbdfe72e31dd489ea0f8aa2", 3536786}, - {"demo5.vmd", 0, "2abb7b6a26406c984f389f0b24b5e28e", 13290970}, - {"demoita.vmd", 0, "b4c0622d14c8749965cd0f5dfca4cf4b", 1183566}, - {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250}, - {0, 0, 0, 0} - }, - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640 | kFeaturesSCNDemo, - 0, 0, 5 - }, - { - { - "playtoons1", - "Non-Interactive Demo", - { - {"s.scn", 0, "1f527010626b5490761f16ba7a6f639a", 251}, - {"demaresp.vmd", 0, "3f860f944056842b35a5fd05416f208e", 5720619}, - {"demboues.vmd", 0, "3a0caa10c98ef92a15942f8274075b43", 3535838}, - {"demo5.vmd", 0, "2abb7b6a26406c984f389f0b24b5e28e", 13290970}, - {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250}, - {0, 0, 0, 0} - }, - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640 | kFeaturesSCNDemo, - 0, 0, 6 - }, - { - { - "playtoons2", - "", - { - {"playtoon.stk", 0, "4772c96be88a57f0561519e4a1526c62", 24406262}, - {"spirou.stk", 0, "5d9c7644d0c47840169b4d016765cc1a", 9816201}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons2", - "", - { - {"playtoon.stk", 0, "55a85036dd93cce93532d8f743d90074", 17467154}, - {"spirou.stk", 0, "e3e1b6148dd72fafc3637f1a8e5764f5", 9812043}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons2", - "", - { - {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, - {"spirou.stk", 0, "91080dc148de1bbd6a97321c1a1facf3", 9817086}, - {0, 0, 0, 0} - }, - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { // Supplied by scoriae in the forums - { - "playtoons2", - "", - { - {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, - {"spirou.stk", 0, "993737f112ca6a9b33c814273280d832", 9825760}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons3", - "", - { - {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338}, - {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons3", - "", - { - {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, - {"chato.stk", 0, "8fc8d0da5b3e758908d1d7298d497d0b", 6041026}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons3", - "Pack mes histoires anim\xE9""es", - { - {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, - {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons3", - "", - { - {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, - {"chato.stk", 0, "3c6cb3ac8a5a7cf681a19971a92a748d", 6033791}, - {0, 0, 0, 0} - }, - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { // Supplied by Hkz on #scummvm - { - "playtoons3", - "", - { - {"playtoon.stk", 0, "4772c96be88a57f0561519e4a1526c62", 24406262}, - {"chato.stk", 0, "bdef407387112bfcee90e664865ac3af", 6033867}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons4", - "", - { - {"playtoon.stk", 0, "b7f5afa2dc1b0f75970b7c07d175db1b", 24340406}, - {"manda.stk", 0, "92529e0b927191d9898a34c2892e9a3a", 6485072}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { //Supplied by goodoldgeorg in bug report #2820006 - { - "playtoons4", - "", - { - {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, - {"manda.stk", 0, "69a79c9f61b2618e482726f2ff68078d", 6499208}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons5", - "", - { - {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, - {"wakan.stk", 0, "f493bf82851bc5ba74d57de6b7e88df8", 5520153}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "bambou", - "", - { - {"intro.stk", 0, "2f8db6963ff8d72a8331627ebda918f4", 3613238}, - {"bambou.itk", 0, "0875914d31126d0749313428f10c7768", 114440192}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBambou, - kFeatures640, - "intro.stk", "intro.tot", 0 - }, - { - { - "playtnck1", - "", - { - {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024}, - {"dan.itk", 0, "906d67b3e438d5e95ec7ea9e781a94f3", 3000320}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtnck2", - "", - { - {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024}, - {"dan.itk", 0, "74eeb075bd2cb47b243349730264af01", 3213312}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtnck3", - "", - { - {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024}, - {"dan.itk", 0, "9a8f62809eca5a52f429b5b6a8e70f8f", 2861056}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "adi2", - "Adi 2.0 for Teachers", - AD_ENTRY1s("adi2.stk", "da6f1fb68bff32260c5eecdf9286a2f5", 1533168), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeaturesNone, - "adi2.stk", "ediintro.tot", 0 - }, - { // Found in french ADI 2 Francais-Maths CM1. Exact version not specified. - { - "adi2", - "Adi 2", - AD_ENTRY1s("adi2.stk", "23f279615c736dc38320f1348e70c36e", 10817668), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeatures640, - "adi2.stk", "ediintro.tot", 0 - }, - { // Found in french ADI 2 Francais-Maths CE2. Exact version not specified. - { - "adi2", - "Adi 2", - AD_ENTRY1s("adi2.stk", "d4162c4298f9423ecc1fb04965557e90", 11531214), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeatures640, - "adi2.stk", "ediintro.tot", 0 - }, - { - { - "adi2", - "Adi 2", - AD_ENTRY1s("adi2.stk", "29694c5a649298a42f87ae731d6d6f6d", 311132), - EN_ANY, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeaturesNone, - "adi2.stk", "ediintro.tot", 0 - }, - { - { - "adi2", - "Adi 2", - AD_ENTRY1s("adi2.stk", "2a40bb48ccbd4e6fb3f7f0fc2f069d80", 17720132), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeatures640, - "adi2.stk", "ediintro.tot", 0 - }, - { - { - "adi2", - "Adi 2.5", - AD_ENTRY1s("adi2.stk", "fcac60e6627f37aee219575b60859de9", 16944268), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeatures640, - "adi2.stk", "ediintro.tot", 0 - }, - { - { - "adi2", - "Adi 2.5", - AD_ENTRY1s("adi2.stk", "072d5e2d7826a7c055865568ebf918bb", 16934596), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeatures640, - "adi2.stk", "ediintro.tot", 0 - }, - { - { - "adi2", - "Adi 2.6", - AD_ENTRY1s("adi2.stk", "2fb940eb8105b12871f6b88c8c4d1615", 16780058), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeatures640, - "adi2.stk", "ediintro.tot", 0 - }, - { - { - "adi2", - "Adi 2.6", - AD_ENTRY1s("adi2.stk", "fde7d98a67dbf859423b6473796e932a", 18044780), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeatures640, - "adi2.stk", "ediintro.tot", 0 - }, - { - { - "adi2", - "Adi 2.7.1", - AD_ENTRY1s("adi2.stk", "6fa5dffebf5c7243c6af6b8c188ee00a", 19278008), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeatures640, - "adi2.stk", "ediintro.tot", 0 - }, - { - { - "adi2", - "Non-Interactive Demo", - { - {"demo.scn", 0, "8b5ba359fd87d586ad39c1754bf6ea35", 168}, - {"demadi2t.vmd", 0, "08a1b18cfe2015d3b43270da35cc813d", 7250723}, - {"demarch.vmd", 0, "4c4a4616585d40ef3df209e3c3911062", 5622731}, - {"demobou.vmd", 0, "2208b9855775564d15c4a5a559da0aec", 3550511}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeAdi2, - kFeatures640 | kFeaturesSCNDemo, - 0, 0, 1 - }, - { - { - "adi4", - "Addy 4 Grundschule Basis CD", - AD_ENTRY1s("intro.stk", "d2f0fb8909e396328dc85c0e29131ba8", 5847588), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeatures640, - 0, 0, 0 - }, - { - { - "adi4", - "Addy 4 Sekundarstufe Basis CD", - AD_ENTRY1s("intro.stk", "367340e59c461b4fa36651cd74e32c4e", 5847378), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeatures640, - 0, 0, 0 - }, - { - { - "adi4", - "Adi 4.0", - AD_ENTRY1s("intro.stk", "a3c35d19b2d28ea261d96321d208cb5a", 6021466), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeatures640, - 0, 0, 0 - }, - { - { - "adi4", - "Adi 4.0", - AD_ENTRY1s("intro.stk", "44491d85648810bc6fcf84f9b3aa47d5", 5834944), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeatures640, - 0, 0, 0 - }, - { - { - "adi4", - "Adi 4.0", - AD_ENTRY1s("intro.stk", "29374c0e3c10b17dd8463b06a55ad093", 6012072), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeatures640, - 0, 0, 0 - }, - { - { - "adi4", - "Adi 4.0 Limited Edition", - AD_ENTRY1s("intro.stk", "ebbbc5e28a4adb695535ed989c1b8d66", 5929644), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeatures640, - 0, 0, 0 - }, - { - { - "adi4", - "ADI 4.10", - AD_ENTRY1s("intro.stk", "3e3fa9656e37d802027635ace88c4cc5", 5359144), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adi4", - "ADI 4.10", - AD_ENTRY1s("intro.stk", "6afc2590856433b9f5295b032f2b205d", 5923112), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adi4", - "ADI 4.11", - AD_ENTRY1s("intro.stk", "6296e4be4e0c270c24d1330881900c7f", 5921234), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adi4", - "Addy 4.21", - AD_ENTRY1s("intro.stk", "534f0b674cd4830df94a9c32c4ea7225", 6878034), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeatures640, - 0, 0, 0 - }, - { - { - "adi4", - "ADI 4.21", - AD_ENTRY1s("intro.stk", "c5b9f6222c0b463f51dab47317c5b687", 5950490), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adi4", - "Adi 4.0 Interactive Demo", - AD_ENTRY1s("intro.stk", "89ace204dbaac001425c73f394334f6f", 2413102), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeatures640, - 0, 0, 0 - }, - { - { - "adi4", - "Adi 4.0 / Adibou 2 Demo", - AD_ENTRY1s("intro.stk", "d41d8cd98f00b204e9800998ecf8427e", 0), - FR_FRA, - kPlatformPC, - ADGF_DEMO, - GUIO_NONE - }, - kGameTypeAdi4, - kFeatures640, - 0, 0, 0 - }, - { - { - "ajworld", - "", - AD_ENTRY1s("intro.stk", "e453bea7b28a67c930764d945f64d898", 3913628), - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "adibou1", - "ADIBOU 1 Environnement 4-7 ans", - AD_ENTRY1s("intro.stk", "6db110188fcb7c5208d9721b5282682a", 4805104), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeAdibou1, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "adibou2", - "ADIBOU 2", - AD_ENTRY1s("intro.stk", "94ae7004348dc8bf99c23a9a6ef81827", 956162), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adibou2", - "Le Jardin Magique d'Adibou", - AD_ENTRY1s("intro.stk", "a8ff86f3cc40dfe5898e0a741217ef27", 956328), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adibou2", - "ADIBOU 2", - AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adibou2", - "ADIB\xD9 2", - AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adibou2", - "ADIBOU Version Decouverte", - AD_ENTRY1s("intro.stk", "558c14327b79ed39214b49d567a75e33", 8737856), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adibou2", - "ADIBOU 2.10 Environnement", - AD_ENTRY1s("intro.stk", "f2b797819aeedee557e904b0b5ccd82e", 8736454), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adibou2", - "ADIBOU 2.11 Environnement", - AD_ENTRY1s("intro.stk", "7b1f1f6f6477f54401e95d913f75e333", 8736904), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adibou2", - "ADIBOU 2.12 Environnement", - AD_ENTRY1s("intro.stk", "1e49c39a4a3ce6032a84b712539c2d63", 8738134), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adibou2", - "ADIBOU 2.13s Environnement", - AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adibou2", - "ADIBOO 2.14 Environnement", - AD_ENTRY1s("intro.stk", "ff63637e3cb7f0a457edf79457b1c6b3", 9333874), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { AD_TABLE_END_MARKER, kGameTypeNone, kFeaturesNone, 0, 0, 0} -}; - -static const GOBGameDescription fallbackDescs[] = { - { //0 - { - "gob1", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesNone, - 0, 0, 0 - }, - { //1 - { - "gob1cd", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { //2 - { - "gob2", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { //3 - { - "gob2mac", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { //4 - { - "gob2cd", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { //5 - { - "bargon", - "", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBargon, - kFeaturesNone, - 0, 0, 0 - }, - { //6 - { - "gob3", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { //7 - { - "gob3cd", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { //8 - { - "woodruff", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { //9 - { - "lostintime", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { //10 - { - "lostintime", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { //11 - { - "lostintime", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { //12 - { - "urban", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeUrban, - kFeaturesCD, - 0, 0, 0 - }, - { //13 - { - "playtoons1", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - 0, 0, 0 - }, - { //14 - { - "playtoons2", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - 0, 0, 0 - }, - { //15 - { - "playtoons3", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - 0, 0, 0 - }, - { //16 - { - "playtoons4", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - 0, 0, 0 - }, - { //17 - { - "playtoons5", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - 0, 0, 0 - }, - { //18 - { - "playtoons construction kit", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - 0, 0, 0 - }, - { //19 - { - "bambou", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBambou, - kFeatures640, - 0, 0, 0 - }, - { //20 - { - "fascination", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesNone, - "disk0.stk", 0, 0 - }, - { //21 - { - "geisha", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGeisha, - kFeaturesNone, - "disk1.stk", "intro.tot", 0 - }, - { //22 - { - "adi2", - "", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeAdi2, - kFeatures640, - "adi2.stk", 0, 0 - }, - { //23 - { - "adi4", - "", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeAdi4, - kFeatures640, - "adif41.stk", 0, 0 - }, - { //24 - { - "coktelplayer", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeUrban, - kFeaturesAdLib | kFeatures640 | kFeaturesSCNDemo, - "", "", 8 - } -}; - -static const ADFileBasedFallback fileBased[] = { - { &fallbackDescs[ 0], { "intro.stk", "disk1.stk", "disk2.stk", "disk3.stk", "disk4.stk", 0 } }, - { &fallbackDescs[ 1], { "intro.stk", "gob.lic", 0 } }, - { &fallbackDescs[ 2], { "intro.stk", 0 } }, - { &fallbackDescs[ 2], { "intro.stk", "disk2.stk", "disk3.stk", 0 } }, - { &fallbackDescs[ 3], { "intro.stk", "disk2.stk", "disk3.stk", "musmac1.mid", 0 } }, - { &fallbackDescs[ 4], { "intro.stk", "gobnew.lic", 0 } }, - { &fallbackDescs[ 5], { "intro.stk", "scaa.imd", "scba.imd", "scbf.imd", 0 } }, - { &fallbackDescs[ 6], { "intro.stk", "imd.itk", 0 } }, - { &fallbackDescs[ 7], { "intro.stk", "mus_gob3.lic", 0 } }, - { &fallbackDescs[ 8], { "intro.stk", "woodruff.itk", 0 } }, - { &fallbackDescs[ 9], { "intro.stk", "commun1.itk", 0 } }, - { &fallbackDescs[10], { "intro.stk", "commun1.itk", "musmac1.mid", 0 } }, - { &fallbackDescs[11], { "intro.stk", "commun1.itk", "lost.lic", 0 } }, - { &fallbackDescs[12], { "intro.stk", "cd1.itk", "objet1.itk", 0 } }, - { &fallbackDescs[13], { "playtoon.stk", "archi.stk", 0 } }, - { &fallbackDescs[14], { "playtoon.stk", "spirou.stk", 0 } }, - { &fallbackDescs[15], { "playtoon.stk", "chato.stk", 0 } }, - { &fallbackDescs[16], { "playtoon.stk", "manda.stk", 0 } }, - { &fallbackDescs[17], { "playtoon.stk", "wakan.stk", 0 } }, - { &fallbackDescs[18], { "playtoon.stk", "dan.itk" } }, - { &fallbackDescs[19], { "intro.stk", "bambou.itk", 0 } }, - { &fallbackDescs[20], { "disk0.stk", "disk1.stk", "disk2.stk", "disk3.stk", 0 } }, - { &fallbackDescs[21], { "disk1.stk", "disk2.stk", "disk3.stk", 0 } }, - { &fallbackDescs[22], { "adi2.stk", 0 } }, - { &fallbackDescs[23], { "adif41.stk", "adim41.stk", 0 } }, - { &fallbackDescs[24], { "coktelplayer.scn", 0 } }, - { 0, { 0 } } -}; - -} +#include "gob/detection_tables.h" static const ADParams detectionParams = { // Pointer to ADGameDescription or its superset structure @@ -5094,7 +107,11 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NOLAUNCHLOAD + Common::GUIO_NOLAUNCHLOAD, + // Maximum directory depth + 1, + // List of directory globs + 0 }; class GobMetaEngine : public AdvancedMetaEngine { diff --git a/engines/gob/detection_tables.h b/engines/gob/detection_tables.h new file mode 100644 index 0000000000..20edb9fbc3 --- /dev/null +++ b/engines/gob/detection_tables.h @@ -0,0 +1,5013 @@ +/* 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$ + * + */ + +namespace Gob { + +using Common::GUIO_NOSPEECH; +using Common::GUIO_NOSUBTITLES; +using Common::GUIO_NONE; + +static const GOBGameDescription gameDescriptions[] = { + { // Supplied by Florian Zeitz on scummvm-devel + { + "gob1", + "EGA", + AD_ENTRY1("intro.stk", "c65e9cc8ba23a38456242e1f2b1caad4"), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesEGA, + 0, 0, 0 + }, + { + { + "gob1", + "EGA", + AD_ENTRY1("intro.stk", "f9233283a0be2464248d83e14b95f09c"), + RU_RUS, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesEGA, + 0, 0, 0 + }, + { // Supplied by Theruler76 in bug report #1201233 + { + "gob1", + "VGA", + AD_ENTRY1("intro.stk", "26a9118c0770fa5ac93a9626761600b2"), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by raziel_ in bug report #1891864 + { + "gob1", + "VGA", + AD_ENTRY1s("intro.stk", "e157cb59c6d330ca70d12ab0ef1dd12b", 288972), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by raina in the forums + { + "gob1", + "", + AD_ENTRY1s("intro.stk", "6d837c6380d8f4d984c9f6cc0026df4f", 192712), + EN_ANY, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by paul66 in bug report #1652352 + { + "gob1", + "", + AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), + EN_ANY, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by paul66 in bug report #1652352 + { + "gob1", + "", + AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), + DE_DEU, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by paul66 in bug report #1652352 + { + "gob1", + "", + AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), + FR_FRA, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by paul66 in bug report #1652352 + { + "gob1", + "", + AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), + IT_ITA, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by paul66 in bug report #1652352 + { + "gob1", + "", + AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), + ES_ESP, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "gob1", + "", + { + {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "gob1", + "", + { + {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + IT_ITA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "gob1", + "", + { + {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "gob1", + "", + { + {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "gob1", + "", + { + {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob1", + "", + { + {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob1", + "", + { + {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob1", + "", + { + {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob1", + "", + { + {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + IT_ITA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob1", + "", + { + {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Found in Found in french ADI 2.5 Anglais Multimedia 5e + { + "gob1", + "", + AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Found in Found in french ADI 2.5 Anglais Multimedia 5e + { + "gob1", + "", + AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Found in Found in french ADI 2.5 Anglais Multimedia 5e + { + "gob1", + "", + AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Found in Found in french ADI 2.5 Anglais Multimedia 5e + { + "gob1", + "", + AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), + IT_ITA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Found in Found in french ADI 2.5 Anglais Multimedia 5e + { + "gob1", + "", + AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // CD 1.000 version. + { + "gob1cd", + "v1.000", + AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // CD 1.000 version. + { + "gob1cd", + "v1.000", + AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // CD 1.000 version. + { + "gob1cd", + "v1.000", + AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // CD 1.000 version. + { + "gob1cd", + "v1.000", + AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // CD 1.000 version. + { + "gob1cd", + "v1.000", + AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // CD 1.02 version. Multilingual + { + "gob1cd", + "v1.02", + AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // CD 1.02 version. Multilingual + { + "gob1cd", + "v1.02", + AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // CD 1.02 version. Multilingual + { + "gob1cd", + "v1.02", + AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // CD 1.02 version. Multilingual + { + "gob1cd", + "v1.02", + AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // CD 1.02 version. Multilingual + { + "gob1cd", + "v1.02", + AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob1cd", + "v1.02", + AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), + HU_HUN, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob1cd", + "v1.02", + AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob1cd", + "v1.02", + AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob1cd", + "v1.02", + AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "gob1", + "Demo", + AD_ENTRY1("intro.stk", "972f22c6ff8144a6636423f0354ca549"), + UNK_LANG, + kPlatformAmiga, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "gob1", + "Interactive Demo", + AD_ENTRY1("intro.stk", "e72bd1e3828c7dec4c8a3e58c48bdfdb"), + UNK_LANG, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "gob1", + "Interactive Demo", + AD_ENTRY1s("intro.stk", "a796096280d5efd48cf8e7dfbe426eb5", 193595), + UNK_LANG, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2785958 + { + "gob1", + "Interactive Demo", + AD_ENTRY1s("intro.stk", "35a098571af9a03c04e2303aec7c9249", 116582), + FR_FRA, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "gob1", + "", + AD_ENTRY1s("intro.stk", "0e022d3f2481b39e9175d37b2c6ad4c6", 2390121), + FR_FRA, + kPlatformCDi, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, "AVT003.TOT", 0 + }, + { // Supplied by fac76 in bug report #1883808 + { + "gob2", + "", + AD_ENTRY1s("intro.stk", "eebf2810122cfd17399260cd1468e994", 554014), + EN_ANY, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "gob2", + "", + AD_ENTRY1("intro.stk", "d28b9e9b41f31acfa58dcd12406c7b2c"), + DE_DEU, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2602057 + { + "gob2", + "", + AD_ENTRY1("intro.stk", "686c88f7302a80b744aae9f8413e853d"), + IT_ITA, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by bgk in bug report #1706861 + { + "gob2", + "", + AD_ENTRY1s("intro.stk", "4b13c02d1069b86bcfec80f4e474b98b", 554680), + FR_FRA, + kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by fac76 in bug report #1673397 + { + "gob2", + "", + { + {"intro.stk", 0, "b45b984ee8017efd6ea965b9becd4d66", 828443}, + {"musmac1.mid", 0, "7f96f491448c7a001b32df89cf8d2af2", 1658}, + {0, 0, 0, 0} + }, + UNK_LANG, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by koalet in bug report #2478585 + { + "gob2", + "", + { + {"intro.stk", 0, "a13ecb4f6d8fd881ebbcc02e45cb5475", 837275}, + {"musmac1.mid", 0, "7f96f491448c7a001b32df89cf8d2af2", 1658}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + AD_ENTRY1("intro.stk", "b45b984ee8017efd6ea965b9becd4d66"), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + AD_ENTRY1("intro.stk", "dedb5d31d8c8050a8cf77abedcc53dae"), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by raziel_ in bug report #1891867 + { + "gob2", + "", + AD_ENTRY1s("intro.stk", "25a99827cd59751a80bed9620fb677a0", 893302), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + AD_ENTRY1s("intro.stk", "a13ecb4f6d8fd881ebbcc02e45cb5475", 837275), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by blackwhiteeagle in bug report #1605235 + { + "gob2", + "", + AD_ENTRY1("intro.stk", "3e4e7db0d201587dd2df4003b2993ef6"), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + AD_ENTRY1("intro.stk", "a13892cdf4badda85a6f6fb47603a128"), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2602017 + { + "gob2", + "", + AD_ENTRY1("intro.stk", "c47faf1d406504e6ffe63243610bb1f4"), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + AD_ENTRY1("intro.stk", "cd3e1df8b273636ee32e34b7064f50e8"), + RU_RUS, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by arcepi in bug report #1659884 + { + "gob2", + "", + AD_ENTRY1s("intro.stk", "5f53c56e3aa2f1e76c2e4f0caa15887f", 829232), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + { + {"intro.stk", 0, "285d7340f98ebad65d465585da12910b", 837286}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + { + {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {0, 0, 0, 0} + }, + EN_USA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + { + {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + { + {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {0, 0, 0, 0} + }, + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + { + {"intro.stk", 0, "6efac0a14c0de4d57dde8592456c8acf", 845172}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {0, 0, 0, 0} + }, + EN_USA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + { + {"intro.stk", 0, "6efac0a14c0de4d57dde8592456c8acf", 845172}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Found in french ADI 2 Francais-Maths CM1 + { + "gob2", + "", + AD_ENTRY1s("intro.stk", "24489330a1d67ff978211f574822a5a6", 883756), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Found in french ADI 2.5 Anglais Multimedia 5e + { + "gob2", + "", + AD_ENTRY1s("intro.stk", "285d7340f98ebad65d465585da12910b", 837286), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2cd", + "v1.000", + AD_ENTRY1("intro.stk", "9de5fbb41cf97182109e5fecc9d90347"), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "gob2cd", + "v2.01", + AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "gob2cd", + "v2.01", + AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "gob2cd", + "v2.01", + AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "gob2cd", + "v2.01", + AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "gob2cd", + "v2.01", + AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + HU_HUN, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "gob2", + "Non-Interactive Demo", + AD_ENTRY1("intro.stk", "8b1c98ff2ab2e14f47a1b891e9b92217"), + UNK_LANG, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, "usa.tot", 0 + }, + { + { + "gob2", + "Interactive Demo", + AD_ENTRY1("intro.stk", "cf1c95b2939bd8ff58a25c756cb6125e"), + UNK_LANG, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "Interactive Demo", + AD_ENTRY1("intro.stk", "4b278c2678ea01383fd5ca114d947eea"), + UNK_LANG, + kPlatformAmiga, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by polluks in bug report #1895126 + { + "gob2", + "Interactive Demo", + AD_ENTRY1s("intro.stk", "9fa85aea959fa8c582085855fbd99346", 553063), + UNK_LANG, + kPlatformAmiga, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by vampir_raziel in bug report #1658373 + { + "ween", + "", + { + {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570}, + {"ween.ins", 0, "d2cb24292c9ddafcad07e23382027218", 87800}, + {0, 0, 0, 0} + }, + EN_GRB, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by vampir_raziel in bug report #1658373 + { + "ween", + "", + AD_ENTRY1s("intro.stk", "257fe669705ac4971efdfd5656eef16a", 457719), + FR_FRA, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by vampir_raziel in bug report #1658373 + { + "ween", + "", + AD_ENTRY1s("intro.stk", "dffd1ab98fe76150d6933329ca6f4cc4", 459458), + FR_FRA, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by vampir_raziel in bug report #1658373 + { + "ween", + "", + AD_ENTRY1s("intro.stk", "af83debf2cbea21faa591c7b4608fe92", 458192), + DE_DEU, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2563539 + { + "ween", + "", + { + {"intro.stk", 0, "dffd1ab98fe76150d6933329ca6f4cc4", 459458}, + {"ween.ins", 0, "d2cb24292c9ddafcad07e23382027218", 87800}, + {0, 0, 0, 0} + }, + IT_ITA, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by pwigren in bug report #1764174 + { + "ween", + "", + { + {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570}, + {"music__5.snd", 0, "7d1819b9981ecddd53d3aacbc75f1cc8", 13446}, + {0, 0, 0, 0} + }, + EN_GRB, + kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "ween", + "", + AD_ENTRY1("intro.stk", "e6d13fb3b858cb4f78a8780d184d5b2c"), + FR_FRA, + kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "ween", + "", + AD_ENTRY1("intro.stk", "2bb8878a8042244dd2b96ff682381baa"), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "ween", + "", + AD_ENTRY1s("intro.stk", "de92e5c6a8c163007ffceebef6e67f7d", 7117568), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by cybot_tmin in bug report #1667743 + { + "ween", + "", + AD_ENTRY1s("intro.stk", "6d60f9205ecfbd8735da2ee7823a70dc", 7014426), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "ween", + "", + AD_ENTRY1("intro.stk", "4b10525a3782aa7ecd9d833b5c1d308b"), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by cartman_ on #scummvm + { + "ween", + "", + AD_ENTRY1("intro.stk", "63170e71f04faba88673b3f510f9c4c8"), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by glorfindel in bugreport #1722142 + { + "ween", + "", + AD_ENTRY1s("intro.stk", "8b57cd510da8a3bbd99e3a0297a8ebd1", 7018771), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "ween", + "Demo", + AD_ENTRY1("intro.stk", "2e9c2898f6bf206ede801e3b2e7ee428"), + UNK_LANG, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesAdLib, + 0, "show.tot", 0 + }, + { + { + "ween", + "Demo", + AD_ENTRY1("intro.stk", "15fb91a1b9b09684b28ac75edf66e504"), + EN_USA, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesAdLib, + 0, "show.tot", 0 + }, + { + { + "bargon", + "", + AD_ENTRY1("intro.stk", "da3c54be18ab73fbdb32db24624a9c23"), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBargon, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by Trekky in the forums + { + "bargon", + "", + AD_ENTRY1s("intro.stk", "2f54b330d21f65b04b7c1f8cca76426c", 262109), + FR_FRA, + kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBargon, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by cesardark in bug #1681649 + { + "bargon", + "", + AD_ENTRY1s("intro.stk", "11103b304286c23945560b391fd37e7d", 3181890), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBargon, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by paul66 in bug #1692667 + { + "bargon", + "", + AD_ENTRY1s("intro.stk", "da3c54be18ab73fbdb32db24624a9c23", 3181825), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBargon, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by pwigren in bugreport #1764174 + { + "bargon", + "", + AD_ENTRY1s("intro.stk", "569d679fe41d49972d34c9fce5930dda", 269825), + EN_ANY, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBargon, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by kizkoool in bugreport #2089734 + { + "bargon", + "", + AD_ENTRY1s("intro.stk", "00f6b4e2ee26e5c40b488e2df5adcf03", 3975580), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBargon, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by glorfindel in bugreport #1722142 + { + "bargon", + "Fanmade", + AD_ENTRY1s("intro.stk", "da3c54be18ab73fbdb32db24624a9c23", 3181825), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBargon, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "littlered", + "", + { + {"intro.stk", 0, "0b72992f5d8b5e6e0330572a5753ea25", 256490}, + {"mod.babayaga", 0, "43484cde74e0860785f8e19f0bc776d1", 60248}, + {0, 0, 0, 0} + }, + UNK_LANG, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), + IT_ITA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { // Found in french ADI 2 Francais-Maths CM1 + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { // Found in french ADI 2 Francais-Maths CM1 + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { // Found in french ADI 2 Francais-Maths CM1 + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { // Found in french ADI 2 Francais-Maths CM1 + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), + IT_ITA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { // Found in french ADI 2 Francais-Maths CM1 + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "7b7f48490dedc8a7cb999388e2fadbe3", 3930674), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "e0767783ff662ed93665446665693aef", 4371238), + HE_ISR, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by cartman_ on #scummvm + { + "lit", + "", + AD_ENTRY1s("intro.stk", "f1f78b663893b58887add182a77df151", 3944090), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2105220 + { + "lit", + "", + AD_ENTRY1s("intro.stk", "cd322cb3c64ef2ba2f2134aa2122cfe9", 3936700), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by koalet in bug report #2479034 + { + "lit", + "", + { + {"intro.stk", 0, "af98bcdc70e1f1c1635577fd726fe7f1", 3937310}, + {"musmac1.mid", 0, "ae7229bb09c6abe4e60a2768b24bc890", 9398}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by SiRoCs in bug report #2093672 + { + "lit", + "", + AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by SiRoCs in bug report #2093672 + { + "lit", + "", + AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by SiRoCs in bug report #2093672 + { + "lit", + "", + AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by SiRoCs in bug report #2093672 + { + "lit", + "", + AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by SiRoCs in bug report #2093672 + { + "lit", + "", + AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by SiRoCs in bug report #2093672 + { + "lit", + "", + AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330), + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330), + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4219382), + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4219382), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Found in french ADI 2.6 Francais-Maths 4e + { + "lit", + "", + AD_ENTRY1s("intro.stk", "58ee9583a4fb837f02d9a58e5f442656", 3937120), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit1", + "Full install", + { + {"intro.stk", 0, "93c91bc9e783d00033042ae83144d7dd", 72318}, + {"partie2.itk", 0, "78f00bd8eb9e680e6289bba0130b1b33", 4396644}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit1", + "Light install", + { + {"intro.stk", 0, "93c91bc9e783d00033042ae83144d7dd", 72318}, + {"partie2.itk", 0, "78f00bd8eb9e680e6289bba0130b1b33", 664064}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit2", + "Light install", + AD_ENTRY1s("intro.stk", "17acbb212e62addbe48dc8f2282c98cb", 72318), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit2", + "Full install", + { + {"intro.stk", 0, "17acbb212e62addbe48dc8f2282c98cb", 72318}, + {"partie4.itk", 0, "6ce4967e0c79d7daeabc6c1d26783d4c", 2612087}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit", + "Demo", + AD_ENTRY1("demo.stk", "c06f8cc20eb239d4c71f225ce3093edf"), + UNK_LANG, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + "demo.stk", "demo.tot", 0 + }, + { + { + "lit", + "Non-interactive Demo", + AD_ENTRY1("demo.stk", "2eba8abd9e3878c57307576012dd2fec"), + UNK_LANG, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + "demo.stk", "demo.tot", 0 + }, + { + { + "fascination", + "CD Version (Censored)", + AD_ENTRY1s("disk0.stk", "9c61e9c22077f72921f07153e37ccf01", 545953), + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES + }, + kGameTypeFascination, + kFeaturesCD, + "disk0.stk", 0, 0 + }, + { + { + "fascination", + "VGA 3 disks edition", + AD_ENTRY1s("disk0.stk", "a50a8495e1b2d67699fb562cb98fc3e2", 1064387), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesAdLib, + "disk0.stk", 0, 0 + }, + { + { + "fascination", + "VGA 3 disks edition", + AD_ENTRY1s("intro.stk", "d6e45ce548598727e2b5587a99718eba", 1055909), + HE_ISR, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesAdLib, + "intro.stk", 0, 0 + }, + { // Supplied by sanguine + { + "fascination", + "VGA 3 disks edition", + AD_ENTRY1s("disk0.stk", "c14330d052fe4da5a441ac9d81bc5891", 1061955), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesAdLib, + "disk0.stk", 0, 0 + }, + { // Supplied by windlepoons in bug report #2809247 + { + "fascination", + "VGA 3 disks edition", + AD_ENTRY1s("disk0.stk", "3a24e60a035250189643c86a9ceafb97", 1062480), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesAdLib, + "disk0.stk", 0, 0 + }, + { + { + "fascination", + "VGA", + AD_ENTRY1s("disk0.stk", "e8ab4f200a2304849f462dc901705599", 183337), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesAdLib, + "disk0.stk", 0, 0 + }, + { + { + "fascination", + "", + AD_ENTRY1s("disk0.stk", "68b1c01564f774c0b640075fbad1b695", 189968), + DE_DEU, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesNone, + "disk0.stk", 0, 0 + }, + { + { + "fascination", + "", + AD_ENTRY1s("disk0.stk", "7062117e9c5adfb6bfb2dac3ff74df9e", 189951), + EN_ANY, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesNone, + "disk0.stk", 0, 0 + }, + { + { + "fascination", + "", + AD_ENTRY1s("disk0.stk", "55c154e5a3e8e98afebdcff4b522e1eb", 190005), + FR_FRA, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesNone, + "disk0.stk", 0, 0 + }, + { + { + "fascination", + "", + AD_ENTRY1s("disk0.stk", "7691827fff35df7799f14cfd6be178ad", 189931), + IT_ITA, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesNone, + "disk0.stk", 0, 0 + }, + { + { + "fascination", + "", + AD_ENTRY1s("disk0.stk", "aff9fcc619f4dd19eae228affd0d34c8", 189964), + EN_ANY, + kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesNone, + "disk0.stk", 0, 0 + }, + { + { + "geisha", + "", + AD_ENTRY1s("disk1.stk", "6eebbb98ad90cd3c44549fc2ab30f632", 212153), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGeisha, + kFeaturesNone, + "disk1.stk", "intro.tot", 0 + }, + { + { + "geisha", + "", + AD_ENTRY1s("disk1.stk", "f4d4d9d20f7ad1f879fc417d47faba89", 336732), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGeisha, + kFeaturesNone, + "disk1.stk", "intro.tot", 0 + }, + { + { + "gob3", + "", + AD_ENTRY1s("intro.stk", "32b0f57f5ae79a9ae97e8011df38af42", 157084), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + AD_ENTRY1s("intro.stk", "904fc32032295baa3efb3a41f17db611", 178582), + HE_ISR, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by raziel_ in bug report #1891869 + { + "gob3", + "", + AD_ENTRY1s("intro.stk", "16b014bf32dbd6ab4c5163c44f56fed1", 445104), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + { + {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104}, + {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, + {0, 0, 0, 0} + }, + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + { + {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104}, + {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + { + {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104}, + {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, + {0, 0, 0, 0} + }, + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by fac76 in bug report #1742716 + { + "gob3", + "", + { + {"intro.stk", 0, "32b0f57f5ae79a9ae97e8011df38af42", 157084}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {0, 0, 0, 0} + }, + EN_GRB, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + AD_ENTRY1("intro.stk", "1e2f64ec8dfa89f42ee49936a27e66e7"), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by paul66 in bug report #1652352 + { + "gob3", + "", + AD_ENTRY1("intro.stk", "f6d225b25a180606fa5dbe6405c97380"), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + AD_ENTRY1("intro.stk", "e42a4f2337d6549487a80864d7826972"), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by Paranoimia on #scummvm + { + "gob3", + "", + AD_ENTRY1s("intro.stk", "fe8144daece35538085adb59c2d29613", 159402), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + AD_ENTRY1("intro.stk", "4e3af248a48a2321364736afab868527"), + RU_RUS, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + AD_ENTRY1("intro.stk", "8d28ce1591b0e9cc79bf41cad0fc4c9c"), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by SiRoCs in bug report #2098621 + { + "gob3", + "", + AD_ENTRY1s("intro.stk", "d3b72938fbbc8159198088811f9e6d19", 160382), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + AD_ENTRY1("intro.stk", "bd679eafde2084d8011f247e51b5a805"), + EN_GRB, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesNone, + 0, "menu.tot", 0 + }, + { + { + "gob3", + "", + AD_ENTRY1("intro.stk", "bd679eafde2084d8011f247e51b5a805"), + DE_DEU, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesNone, + 0, "menu.tot", 0 + }, + { + { + "gob3", + "", + { + {"intro.stk", 0, "edd7403e5dc2a14459d2665a4c17714d", 209534}, + {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + { + {"intro.stk", 0, "428e2de130cf3b303c938924539dc50d", 324420}, + {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + { + {"intro.stk", 0, "428e2de130cf3b303c938924539dc50d", 324420}, + {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Found in Found in french ADI 2.5 Anglais Multimedia 5e + { + "gob3", + "", + AD_ENTRY1s("intro.stk", "edd7403e5dc2a14459d2665a4c17714d", 209534), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3cd", + "v1.000", + AD_ENTRY1("intro.stk", "6f2c226c62dd7ab0ab6f850e89d3fc47"), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 + { + "gob3cd", + "v1.02", + AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 + { + "gob3cd", + "v1.02", + AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 + { + "gob3cd", + "v1.02", + AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 + { + "gob3cd", + "v1.02", + AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 + { + "gob3cd", + "v1.02", + AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob3cd", + "v1.02", + AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), + HU_HUN, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob3cd", + "v1.02", + AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob3cd", + "v1.02", + AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob3cd", + "v1.02", + AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "gob3", + "Interactive Demo", + AD_ENTRY1("intro.stk", "7aebd94e49c2c5c518c9e7b74f25de9d"), + FR_FRA, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "Interactive Demo 2", + AD_ENTRY1("intro.stk", "e5dcbc9f6658ebb1e8fe26bc4da0806d"), + FR_FRA, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "Interactive Demo 3", + AD_ENTRY1s("intro.stk", "9e20ad7b471b01f84db526da34eaf0a2", 395561), + EN_ANY, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "Non-interactive Demo", + AD_ENTRY1("intro.stk", "b9b898fccebe02b69c086052d5024a55"), + UNK_LANG, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), + EN_USA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), + IT_ITA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "inca2", + "Non-Interactive Demo", + { + {"cons.imd", 0, "f896ba0c4a1ac7f7260d342655980b49", 17804}, + {"conseil.imd", 0, "aaedd5482d5b271e233e86c5a03cf62e", 33999}, + {"int.imd", 0, "6308222fcefbcb20925f01c1aff70dee", 30871}, + {"inter.imd", 0, "39bd6d3540f3bedcc97293f352c7f3fc", 191719}, + {"machu.imd", 0, "c0bc8211d93b467bfd063b63fe61b85c", 34609}, + {"post.imd", 0, "d75cad0e3fc22cb0c8b6faf597f509b2", 1047709}, + {"posta.imd", 0, "2a5b3fe75681ddf4d21ac724db8111b4", 547250}, + {"postb.imd", 0, "24260ce4e80a4c472352b76637265d09", 868312}, + {"postc.imd", 0, "24accbcc8b83a9c2be4bd82849a2bd29", 415637}, + {"tum.imd", 0, "0993d4810ec9deb3f77c5e92095320fd", 20330}, + {"tumi.imd", 0, "bf53f229480d694de0947fe3366fbec6", 248952}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdLib | kFeaturesBATDemo, + 0, 0, 7 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "5f5f4e0a72c33391e67a47674b120cc6", 20296422), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by jvprat on #scummvm + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by jvprat on #scummvm + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by jvprat on #scummvm + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by jvprat on #scummvm + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by jvprat on #scummvm + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by DjDiabolik in bug report #1971294 + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by DjDiabolik in bug report #1971294 + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by DjDiabolik in bug report #1971294 + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by DjDiabolik in bug report #1971294 + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by DjDiabolik in bug report #1971294 + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2098838 + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "08a96bf061af1fa4f75c6a7cc56b60a4", 20734979), + PL_POL, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "Non-Interactive Demo", + { + {"demo.scn", 0, "16bb85fc5f8e519147b60475dbf33962", 89}, + {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640 | kFeaturesSCNDemo, + 0, 0, 1 + }, + { + { + "dynasty", + "", + AD_ENTRY1s("intro.stk", "6190e32404b672f4bbbc39cf76f41fda", 2511470), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeDynasty, + kFeatures640, + 0, 0, 0 + }, + { + { + "dynasty", + "", + AD_ENTRY1s("intro.stk", "61e4069c16e27775a6cc6d20f529fb36", 2511300), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeDynasty, + kFeatures640, + 0, 0, 0 + }, + { + { + "dynasty", + "", + AD_ENTRY1s("intro.stk", "61e4069c16e27775a6cc6d20f529fb36", 2511300), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeDynasty, + kFeatures640, + 0, 0, 0 + }, + { + { + "dynasty", + "", + AD_ENTRY1s("intro.stk", "b3f8472484b7a1df94557b51e7b6fca0", 2322644), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeDynasty, + kFeatures640, + 0, 0, 0 + }, + { + { + "dynasty", + "", + AD_ENTRY1s("intro.stk", "bdbdac8919200a5e71ffb9fb0709f704", 2446652), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeDynasty, + kFeatures640, + 0, 0, 0 + }, + { + { + "dynasty", + "Demo", + AD_ENTRY1s("intro.stk", "464538a17ed39755d7f1ba9c751af1bd", 1847864), + EN_USA, + kPlatformPC, + ADGF_DEMO, + GUIO_NONE + }, + kGameTypeDynasty, + kFeatures640, + 0, 0, 0 + }, + { + { + "dynasty", + "Demo", + AD_ENTRY1s("lda1.stk", "0e56a899357cbc0bf503260fd2dd634e", 15032774), + UNK_LANG, + kPlatformWindows, + ADGF_DEMO, + GUIO_NONE + }, + kGameTypeDynasty, + kFeatures640, + "lda1.stk", 0, 0 + }, + { + { + "dynasty", + "Demo", + AD_ENTRY1s("lda1.stk", "8669ea2e9a8239c070dc73958fbc8753", 15567724), + DE_DEU, + kPlatformWindows, + ADGF_DEMO, + GUIO_NONE + }, + kGameTypeDynasty, + kFeatures640, + "lda1.stk", 0, 0 + }, + { + { + "urban", + "", + AD_ENTRY1s("intro.stk", "3ab2c542bd9216ae5d02cc6f45701ae1", 1252436), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeUrban, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by gamin in the forums + { + "urban", + "", + AD_ENTRY1s("intro.stk", "b991ed1d31c793e560edefdb349882ef", 1276408), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeUrban, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by jvprat on #scummvm + { + "urban", + "", + AD_ENTRY1s("intro.stk", "4ec3c0864e2b54c5b4ccf9f6ad96528d", 1253328), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeUrban, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2770340 + { + "urban", + "", + AD_ENTRY1s("intro.stk", "4bd31979ea3d77a58a358c09000a85ed", 1253018), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeUrban, + kFeatures640, + 0, 0, 0 + }, + { + { + "urban", + "Non-Interactive Demo", + { + {"wdemo.s24", 0, "14ac9bd51db7a075d69ddb144904b271", 87}, + {"demo.vmd", 0, "65d04715d871c292518b56dd160b0161", 9091237}, + {"urband.vmd", 0, "60343891868c91854dd5c82766c70ecc", 922461}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeUrban, + kFeatures640 | kFeaturesSCNDemo, + 0, 0, 2 + }, + { + { + "playtoons1", + "", + { + {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338}, + {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons1", + "Pack mes histoires anim\xE9""es", + { + {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, + {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons1", + "", + { + {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, + {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674}, + {0, 0, 0, 0} + }, + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { // Supplied by scoriae in the forums + { + "playtoons1", + "", + { + {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, + {"archi.stk", 0, "00d8274519dfcf8a0d8ae3099daea0f8", 5532135}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons1", + "Non-Interactive Demo", + { + {"play123.scn", 0, "4689a31f543915e488c3bc46ea358add", 258}, + {"archi.vmd", 0, "a410fcc8116bc173f038100f5857191c", 5617210}, + {"chato.vmd", 0, "5a10e39cb66c396f2f9d8fb35e9ac016", 5445937}, + {"genedeb.vmd", 0, "3bb4a45585f88f4d839efdda6a1b582b", 1244228}, + {"generik.vmd", 0, "b46bdd64b063e86927fb2826500ad512", 603242}, + {"genespi.vmd", 0, "b7611916f32a370ae9832962fc17ef72", 758719}, + {"spirou.vmd", 0, "8513dbf7ac51c057b21d371d6b217b47", 2550788}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640 | kFeaturesSCNDemo, + 0, 0, 3 + }, + { + { + "playtoons1", + "Non-Interactive Demo", + { + {"e.scn", 0, "8a0db733c3f77be86e74e8242e5caa61", 124}, + {"demarchg.vmd", 0, "d14a95da7d8792faf5503f649ffcbc12", 5619415}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640 | kFeaturesSCNDemo, + 0, 0, 4 + }, + { + { + "playtoons1", + "Non-Interactive Demo", + { + {"i.scn", 0, "8b3294474d39970463663edd22341730", 285}, + {"demarita.vmd", 0, "84c8672b91c7312462603446e224bfec", 5742533}, + {"dembouit.vmd", 0, "7a5fdf0a4dbdfe72e31dd489ea0f8aa2", 3536786}, + {"demo5.vmd", 0, "2abb7b6a26406c984f389f0b24b5e28e", 13290970}, + {"demoita.vmd", 0, "b4c0622d14c8749965cd0f5dfca4cf4b", 1183566}, + {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250}, + {0, 0, 0, 0} + }, + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640 | kFeaturesSCNDemo, + 0, 0, 5 + }, + { + { + "playtoons1", + "Non-Interactive Demo", + { + {"s.scn", 0, "1f527010626b5490761f16ba7a6f639a", 251}, + {"demaresp.vmd", 0, "3f860f944056842b35a5fd05416f208e", 5720619}, + {"demboues.vmd", 0, "3a0caa10c98ef92a15942f8274075b43", 3535838}, + {"demo5.vmd", 0, "2abb7b6a26406c984f389f0b24b5e28e", 13290970}, + {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250}, + {0, 0, 0, 0} + }, + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640 | kFeaturesSCNDemo, + 0, 0, 6 + }, + { + { + "playtoons2", + "", + { + {"playtoon.stk", 0, "4772c96be88a57f0561519e4a1526c62", 24406262}, + {"spirou.stk", 0, "5d9c7644d0c47840169b4d016765cc1a", 9816201}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons2", + "", + { + {"playtoon.stk", 0, "55a85036dd93cce93532d8f743d90074", 17467154}, + {"spirou.stk", 0, "e3e1b6148dd72fafc3637f1a8e5764f5", 9812043}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons2", + "", + { + {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, + {"spirou.stk", 0, "91080dc148de1bbd6a97321c1a1facf3", 9817086}, + {0, 0, 0, 0} + }, + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { // Supplied by scoriae in the forums + { + "playtoons2", + "", + { + {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, + {"spirou.stk", 0, "993737f112ca6a9b33c814273280d832", 9825760}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons3", + "", + { + {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338}, + {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons3", + "", + { + {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, + {"chato.stk", 0, "8fc8d0da5b3e758908d1d7298d497d0b", 6041026}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons3", + "Pack mes histoires anim\xE9""es", + { + {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, + {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons3", + "", + { + {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, + {"chato.stk", 0, "3c6cb3ac8a5a7cf681a19971a92a748d", 6033791}, + {0, 0, 0, 0} + }, + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "playtoons3", + "", + { + {"playtoon.stk", 0, "4772c96be88a57f0561519e4a1526c62", 24406262}, + {"chato.stk", 0, "bdef407387112bfcee90e664865ac3af", 6033867}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons4", + "", + { + {"playtoon.stk", 0, "b7f5afa2dc1b0f75970b7c07d175db1b", 24340406}, + {"manda.stk", 0, "92529e0b927191d9898a34c2892e9a3a", 6485072}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { //Supplied by goodoldgeorg in bug report #2820006 + { + "playtoons4", + "", + { + {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, + {"manda.stk", 0, "69a79c9f61b2618e482726f2ff68078d", 6499208}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons5", + "", + { + {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, + {"wakan.stk", 0, "f493bf82851bc5ba74d57de6b7e88df8", 5520153}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "bambou", + "", + { + {"intro.stk", 0, "2f8db6963ff8d72a8331627ebda918f4", 3613238}, + {"bambou.itk", 0, "0875914d31126d0749313428f10c7768", 114440192}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBambou, + kFeatures640, + "intro.stk", "intro.tot", 0 + }, + { + { + "playtnck1", + "", + { + {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024}, + {"dan.itk", 0, "906d67b3e438d5e95ec7ea9e781a94f3", 3000320}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtnck2", + "", + { + {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024}, + {"dan.itk", 0, "74eeb075bd2cb47b243349730264af01", 3213312}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtnck3", + "", + { + {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024}, + {"dan.itk", 0, "9a8f62809eca5a52f429b5b6a8e70f8f", 2861056}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "adi2", + "Adi 2.0 for Teachers", + AD_ENTRY1s("adi2.stk", "da6f1fb68bff32260c5eecdf9286a2f5", 1533168), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeaturesNone, + "adi2.stk", "ediintro.tot", 0 + }, + { // Found in french ADI 2 Francais-Maths CM1. Exact version not specified. + { + "adi2", + "Adi 2", + AD_ENTRY1s("adi2.stk", "23f279615c736dc38320f1348e70c36e", 10817668), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeatures640, + "adi2.stk", "ediintro.tot", 0 + }, + { // Found in french ADI 2 Francais-Maths CE2. Exact version not specified. + { + "adi2", + "Adi 2", + AD_ENTRY1s("adi2.stk", "d4162c4298f9423ecc1fb04965557e90", 11531214), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeatures640, + "adi2.stk", "ediintro.tot", 0 + }, + { + { + "adi2", + "Adi 2", + AD_ENTRY1s("adi2.stk", "29694c5a649298a42f87ae731d6d6f6d", 311132), + EN_ANY, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeaturesNone, + "adi2.stk", "ediintro.tot", 0 + }, + { + { + "adi2", + "Adi 2", + AD_ENTRY1s("adi2.stk", "2a40bb48ccbd4e6fb3f7f0fc2f069d80", 17720132), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeatures640, + "adi2.stk", "ediintro.tot", 0 + }, + { + { + "adi2", + "Adi 2.5", + AD_ENTRY1s("adi2.stk", "fcac60e6627f37aee219575b60859de9", 16944268), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeatures640, + "adi2.stk", "ediintro.tot", 0 + }, + { + { + "adi2", + "Adi 2.5", + AD_ENTRY1s("adi2.stk", "072d5e2d7826a7c055865568ebf918bb", 16934596), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeatures640, + "adi2.stk", "ediintro.tot", 0 + }, + { + { + "adi2", + "Adi 2.6", + AD_ENTRY1s("adi2.stk", "2fb940eb8105b12871f6b88c8c4d1615", 16780058), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeatures640, + "adi2.stk", "ediintro.tot", 0 + }, + { + { + "adi2", + "Adi 2.6", + AD_ENTRY1s("adi2.stk", "fde7d98a67dbf859423b6473796e932a", 18044780), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeatures640, + "adi2.stk", "ediintro.tot", 0 + }, + { + { + "adi2", + "Adi 2.7.1", + AD_ENTRY1s("adi2.stk", "6fa5dffebf5c7243c6af6b8c188ee00a", 19278008), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeatures640, + "adi2.stk", "ediintro.tot", 0 + }, + { + { + "adi2", + "Non-Interactive Demo", + { + {"demo.scn", 0, "8b5ba359fd87d586ad39c1754bf6ea35", 168}, + {"demadi2t.vmd", 0, "08a1b18cfe2015d3b43270da35cc813d", 7250723}, + {"demarch.vmd", 0, "4c4a4616585d40ef3df209e3c3911062", 5622731}, + {"demobou.vmd", 0, "2208b9855775564d15c4a5a559da0aec", 3550511}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeAdi2, + kFeatures640 | kFeaturesSCNDemo, + 0, 0, 1 + }, + { + { + "adi4", + "Addy 4 Grundschule Basis CD", + AD_ENTRY1s("intro.stk", "d2f0fb8909e396328dc85c0e29131ba8", 5847588), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeatures640, + 0, 0, 0 + }, + { + { + "adi4", + "Addy 4 Sekundarstufe Basis CD", + AD_ENTRY1s("intro.stk", "367340e59c461b4fa36651cd74e32c4e", 5847378), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeatures640, + 0, 0, 0 + }, + { + { + "adi4", + "Adi 4.0", + AD_ENTRY1s("intro.stk", "a3c35d19b2d28ea261d96321d208cb5a", 6021466), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeatures640, + 0, 0, 0 + }, + { + { + "adi4", + "Adi 4.0", + AD_ENTRY1s("intro.stk", "44491d85648810bc6fcf84f9b3aa47d5", 5834944), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeatures640, + 0, 0, 0 + }, + { + { + "adi4", + "Adi 4.0", + AD_ENTRY1s("intro.stk", "29374c0e3c10b17dd8463b06a55ad093", 6012072), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeatures640, + 0, 0, 0 + }, + { + { + "adi4", + "Adi 4.0 Limited Edition", + AD_ENTRY1s("intro.stk", "ebbbc5e28a4adb695535ed989c1b8d66", 5929644), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeatures640, + 0, 0, 0 + }, + { + { + "adi4", + "ADI 4.10", + AD_ENTRY1s("intro.stk", "3e3fa9656e37d802027635ace88c4cc5", 5359144), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adi4", + "ADI 4.10", + AD_ENTRY1s("intro.stk", "6afc2590856433b9f5295b032f2b205d", 5923112), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adi4", + "ADI 4.11", + AD_ENTRY1s("intro.stk", "6296e4be4e0c270c24d1330881900c7f", 5921234), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adi4", + "Addy 4.21", + AD_ENTRY1s("intro.stk", "534f0b674cd4830df94a9c32c4ea7225", 6878034), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeatures640, + 0, 0, 0 + }, + { + { + "adi4", + "ADI 4.21", + AD_ENTRY1s("intro.stk", "c5b9f6222c0b463f51dab47317c5b687", 5950490), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adi4", + "Adi 4.0 Interactive Demo", + AD_ENTRY1s("intro.stk", "89ace204dbaac001425c73f394334f6f", 2413102), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeatures640, + 0, 0, 0 + }, + { + { + "adi4", + "Adi 4.0 / Adibou 2 Demo", + AD_ENTRY1s("intro.stk", "d41d8cd98f00b204e9800998ecf8427e", 0), + FR_FRA, + kPlatformPC, + ADGF_DEMO, + GUIO_NONE + }, + kGameTypeAdi4, + kFeatures640, + 0, 0, 0 + }, + { + { + "ajworld", + "", + AD_ENTRY1s("intro.stk", "e453bea7b28a67c930764d945f64d898", 3913628), + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "adibou1", + "ADIBOU 1 Environnement 4-7 ans", + AD_ENTRY1s("intro.stk", "6db110188fcb7c5208d9721b5282682a", 4805104), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeAdibou1, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "adibou2", + "ADIBOU 2", + AD_ENTRY1s("intro.stk", "94ae7004348dc8bf99c23a9a6ef81827", 956162), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adibou2", + "Le Jardin Magique d'Adibou", + AD_ENTRY1s("intro.stk", "a8ff86f3cc40dfe5898e0a741217ef27", 956328), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adibou2", + "ADIBOU 2", + AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adibou2", + "ADIB\xD9 2", + AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adibou2", + "ADIBOU Version Decouverte", + AD_ENTRY1s("intro.stk", "558c14327b79ed39214b49d567a75e33", 8737856), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adibou2", + "ADIBOU 2.10 Environnement", + AD_ENTRY1s("intro.stk", "f2b797819aeedee557e904b0b5ccd82e", 8736454), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adibou2", + "ADIBOU 2.11 Environnement", + AD_ENTRY1s("intro.stk", "7b1f1f6f6477f54401e95d913f75e333", 8736904), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adibou2", + "ADIBOU 2.12 Environnement", + AD_ENTRY1s("intro.stk", "1e49c39a4a3ce6032a84b712539c2d63", 8738134), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adibou2", + "ADIBOU 2.13s Environnement", + AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adibou2", + "ADIBOO 2.14 Environnement", + AD_ENTRY1s("intro.stk", "ff63637e3cb7f0a457edf79457b1c6b3", 9333874), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { AD_TABLE_END_MARKER, kGameTypeNone, kFeaturesNone, 0, 0, 0} +}; + +static const GOBGameDescription fallbackDescs[] = { + { //0 + { + "gob1", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesNone, + 0, 0, 0 + }, + { //1 + { + "gob1cd", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { //2 + { + "gob2", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { //3 + { + "gob2mac", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { //4 + { + "gob2cd", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { //5 + { + "bargon", + "", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBargon, + kFeaturesNone, + 0, 0, 0 + }, + { //6 + { + "gob3", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { //7 + { + "gob3cd", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { //8 + { + "woodruff", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { //9 + { + "lostintime", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { //10 + { + "lostintime", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { //11 + { + "lostintime", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { //12 + { + "urban", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeUrban, + kFeaturesCD, + 0, 0, 0 + }, + { //13 + { + "playtoons1", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + 0, 0, 0 + }, + { //14 + { + "playtoons2", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + 0, 0, 0 + }, + { //15 + { + "playtoons3", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + 0, 0, 0 + }, + { //16 + { + "playtoons4", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + 0, 0, 0 + }, + { //17 + { + "playtoons5", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + 0, 0, 0 + }, + { //18 + { + "playtoons construction kit", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + 0, 0, 0 + }, + { //19 + { + "bambou", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBambou, + kFeatures640, + 0, 0, 0 + }, + { //20 + { + "fascination", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesNone, + "disk0.stk", 0, 0 + }, + { //21 + { + "geisha", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGeisha, + kFeaturesNone, + "disk1.stk", "intro.tot", 0 + }, + { //22 + { + "adi2", + "", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeAdi2, + kFeatures640, + "adi2.stk", 0, 0 + }, + { //23 + { + "adi4", + "", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeAdi4, + kFeatures640, + "adif41.stk", 0, 0 + }, + { //24 + { + "coktelplayer", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeUrban, + kFeaturesAdLib | kFeatures640 | kFeaturesSCNDemo, + "", "", 8 + } +}; + +static const ADFileBasedFallback fileBased[] = { + { &fallbackDescs[ 0], { "intro.stk", "disk1.stk", "disk2.stk", "disk3.stk", "disk4.stk", 0 } }, + { &fallbackDescs[ 1], { "intro.stk", "gob.lic", 0 } }, + { &fallbackDescs[ 2], { "intro.stk", 0 } }, + { &fallbackDescs[ 2], { "intro.stk", "disk2.stk", "disk3.stk", 0 } }, + { &fallbackDescs[ 3], { "intro.stk", "disk2.stk", "disk3.stk", "musmac1.mid", 0 } }, + { &fallbackDescs[ 4], { "intro.stk", "gobnew.lic", 0 } }, + { &fallbackDescs[ 5], { "intro.stk", "scaa.imd", "scba.imd", "scbf.imd", 0 } }, + { &fallbackDescs[ 6], { "intro.stk", "imd.itk", 0 } }, + { &fallbackDescs[ 7], { "intro.stk", "mus_gob3.lic", 0 } }, + { &fallbackDescs[ 8], { "intro.stk", "woodruff.itk", 0 } }, + { &fallbackDescs[ 9], { "intro.stk", "commun1.itk", 0 } }, + { &fallbackDescs[10], { "intro.stk", "commun1.itk", "musmac1.mid", 0 } }, + { &fallbackDescs[11], { "intro.stk", "commun1.itk", "lost.lic", 0 } }, + { &fallbackDescs[12], { "intro.stk", "cd1.itk", "objet1.itk", 0 } }, + { &fallbackDescs[13], { "playtoon.stk", "archi.stk", 0 } }, + { &fallbackDescs[14], { "playtoon.stk", "spirou.stk", 0 } }, + { &fallbackDescs[15], { "playtoon.stk", "chato.stk", 0 } }, + { &fallbackDescs[16], { "playtoon.stk", "manda.stk", 0 } }, + { &fallbackDescs[17], { "playtoon.stk", "wakan.stk", 0 } }, + { &fallbackDescs[18], { "playtoon.stk", "dan.itk" } }, + { &fallbackDescs[19], { "intro.stk", "bambou.itk", 0 } }, + { &fallbackDescs[20], { "disk0.stk", "disk1.stk", "disk2.stk", "disk3.stk", 0 } }, + { &fallbackDescs[21], { "disk1.stk", "disk2.stk", "disk3.stk", 0 } }, + { &fallbackDescs[22], { "adi2.stk", 0 } }, + { &fallbackDescs[23], { "adif41.stk", "adim41.stk", 0 } }, + { &fallbackDescs[24], { "coktelplayer.scn", 0 } }, + { 0, { 0 } } +}; + +} diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index d36a1c65c9..9c61bc1b75 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -345,8 +345,8 @@ void GobEngine::pauseGame() { } bool GobEngine::initGameParts() { - _noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL; - + // just detect some devices some of which will be always there if the music is not disabled + _noMusic = MidiDriver::getMusicType(MidiDriver::detectDevice(MDT_PCSPK | MDT_MIDI | MDT_ADLIB)) == MT_NULL ? true : false; _saveLoad = 0; _global = new Global(this); diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index 805893d8a7..9e841e7e68 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -813,6 +813,14 @@ bool Inter_v1::o1_if(OpFuncParams ¶ms) { byte cmd; bool boolRes; + // WORKAROUND: Windows Gob1 OUTODDV reload goblin stuck bug present in original + if ((_vm->getGameType() == kGameTypeGob1) && (_vm->_game->_script->pos() == 11294) && + !scumm_stricmp(_vm->_game->_curTotFile, "avt00.tot") && VAR(59) == 1) { + warning("Workaround for Win Gob1 OUTODDV Reload Goblin Stuck Bug..."); + WRITE_VAR(285, 0); + WRITE_VAR(59, 0); + } + boolRes = _vm->_game->_script->evalBoolResult(); if (boolRes) { if ((params.counter == params.cmdCount) && (params.retFlag == 2)) @@ -1331,7 +1339,8 @@ bool Inter_v1::o1_goblinFunc(OpFuncParams ¶ms) { gobParams.retVarPtr.set(*_variables, 236); cmd = _vm->_game->_script->readInt16(); - _vm->_game->_script->skip(2); + gobParams.paramCount = _vm->_game->_script->readInt16(); + if ((cmd > 0) && (cmd < 17)) { objDescSet = true; gobParams.extraData = _vm->_game->_script->readInt16(); diff --git a/engines/groovie/cursor.cpp b/engines/groovie/cursor.cpp index 3f304c7859..2d0a2df245 100644 --- a/engines/groovie/cursor.cpp +++ b/engines/groovie/cursor.cpp @@ -403,18 +403,15 @@ GrvCursorMan_v2::GrvCursorMan_v2(OSystem *system) : // Open the icons file Common::File iconsFile; - if (!iconsFile.open("icons.ph")) { + if (!iconsFile.open("icons.ph")) error("Groovie::Cursor: Couldn't open icons.ph"); - return; - } // Verify the signature - uint32 tmp32 = iconsFile.readUint32LE(); + uint32 tmp32 = iconsFile.readUint32BE(); uint16 tmp16 = iconsFile.readUint16LE(); - if (tmp32 != 0x6e6f6369 || tmp16 != 1) { - error("Groovie::Cursor: icons.ph signature failed: %04X %d", tmp32, tmp16); - return; - } + if (tmp32 != MKID_BE('icon') || tmp16 != 1) + error("Groovie::Cursor: icons.ph signature failed: %s %d", tag2str(tmp32), tmp16); + // Read the number of icons uint16 nicons = iconsFile.readUint16LE(); diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp index ec401e7d24..b30c2361d2 100644 --- a/engines/groovie/detection.cpp +++ b/engines/groovie/detection.cpp @@ -176,7 +176,11 @@ static const ADParams detectionParams = { // Flags kADFlagUseExtraAsHint, // Additional GUI options (for every game} - Common::GUIO_NOSUBTITLES | Common::GUIO_NOSFX + Common::GUIO_NOSUBTITLES | Common::GUIO_NOSFX, + // Maximum directory depth + 1, + // List of directory globs + 0 }; diff --git a/engines/groovie/font.cpp b/engines/groovie/font.cpp index 6aa6c89d31..dc1d7ae73a 100644 --- a/engines/groovie/font.cpp +++ b/engines/groovie/font.cpp @@ -54,6 +54,7 @@ bool T7GFont::load(Common::SeekableReadStream &stream) { if (stream.eos()) { error("Groovie::T7GFont: Couldn't read the glyph offsets"); + delete[] glyphOffsets; return false; } diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp index 93675b3d1e..276b26ffe7 100644 --- a/engines/groovie/groovie.cpp +++ b/engines/groovie/groovie.cpp @@ -110,7 +110,7 @@ Common::Error GroovieEngine::run() { // Prepare the font too switch (_gameDescription->version) { case kGroovieT7G: - if (_gameDescription->desc.platform == Common::kPlatformMacintosh) { + if (getPlatform() == Common::kPlatformMacintosh) { _macResFork = new Common::MacResManager(); if (!_macResFork->open(_gameDescription->desc.filesDescriptions[0].fileName)) error("Could not open %s as a resource fork", _gameDescription->desc.filesDescriptions[0].fileName); @@ -141,7 +141,7 @@ Common::Error GroovieEngine::run() { } // Create the music player - if (_gameDescription->desc.platform == Common::kPlatformMacintosh) + if (getPlatform() == Common::kPlatformMacintosh) _musicPlayer = new MusicPlayerMac(this); else _musicPlayer = new MusicPlayerXMI(this, _gameDescription->version == kGroovieT7G ? "fat" : "sample"); @@ -154,8 +154,8 @@ Common::Error GroovieEngine::run() { if (_gameDescription->version == kGroovieT7G) { // Run The 7th Guest's demo if requested if (ConfMan.hasKey("demo_mode") && ConfMan.getBool("demo_mode")) - filename = Common::String("demo.grv"); - else if (_gameDescription->desc.platform == Common::kPlatformMacintosh) + filename = "demo.grv"; + else if (getPlatform() == Common::kPlatformMacintosh) filename = "script.grv"; // Stored inside the executable's resource fork } else if (_gameDescription->version == kGroovieV2) { // Open the disk index @@ -307,6 +307,10 @@ Common::Error GroovieEngine::run() { return Common::kNoError; } +Common::Platform GroovieEngine::getPlatform() const { + return _gameDescription->desc.platform; +} + bool GroovieEngine::hasFeature(EngineFeature f) const { return (f == kSupportsRTL) || diff --git a/engines/groovie/groovie.h b/engines/groovie/groovie.h index 437debfd17..8ae5f4157f 100644 --- a/engines/groovie/groovie.h +++ b/engines/groovie/groovie.h @@ -82,6 +82,8 @@ public: GroovieEngine(OSystem *syst, const GroovieGameDescription *gd); ~GroovieEngine(); + Common::Platform getPlatform() const; + protected: // Engine APIs diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp index f2b190985d..34b180a68e 100644 --- a/engines/groovie/music.cpp +++ b/engines/groovie/music.cpp @@ -110,6 +110,20 @@ void MusicPlayer::playCD(uint8 track) { // Play the track starting at the requested offset (1000ms = 75 frames) g_system->getAudioCDManager()->play(track - 1, 1, startms * 75 / 1000, 0); + + // If the audio is not playing from the CD, play the "fallback" MIDI. + // The Mac version has no CD tracks, so it will always use the MIDI. + if (!g_system->getAudioCDManager()->isPlaying()) { + if (track == 2) { + // Intro MIDI fallback + if (_vm->getPlatform() == Common::kPlatformMacintosh) + playSong(70); + else + playSong((19 << 10) | 36); // XMI.GJD, file 36 + } else if (track == 3) { + // TODO: Credits MIDI fallback + } + } } void MusicPlayer::startBackground() { @@ -385,8 +399,8 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String >lName) _midiParser = MidiParser::createParser_XMIDI(); // Create the driver - MidiDriverType driver = detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - _driver = createMidi(driver); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); + _driver = createMidi(dev); this->open(); // Set the parser's driver @@ -401,9 +415,9 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String >lName) } // Load the Global Timbre Library - if (driver == MD_ADLIB) { + if (MidiDriver::getMusicType(dev) == MT_ADLIB) { // MIDI through AdLib - _musicType = MD_ADLIB; + _musicType = MT_ADLIB; loadTimbres(gtlName + ".ad"); // Setup the percussion channel @@ -411,9 +425,9 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String >lName) if (_timbres[i].bank == 0x7F) setTimbreAD(9, _timbres[i]); } - } else if ((driver == MD_MT32) || ConfMan.getBool("native_mt32")) { + } else if ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")) { // MT-32 - _musicType = MD_MT32; + _musicType = MT_MT32; loadTimbres(gtlName + ".mt"); } else { // GM @@ -454,9 +468,9 @@ void MusicPlayerXMI::send(uint32 b) { for (int i = 0; i < numTimbres; i++) { if ((_timbres[i].bank == _chanBanks[chan]) && (_timbres[i].patch == patch)) { - if (_musicType == MD_ADLIB) { + if (_musicType == MT_ADLIB) { setTimbreAD(chan, _timbres[i]); - } else if (_musicType == MD_MT32) { + } else if (_musicType == MT_MT32) { setTimbreMT(chan, _timbres[i]); } return; @@ -681,8 +695,8 @@ MusicPlayerMac::MusicPlayerMac(GroovieEngine *vm) : MusicPlayerMidi(vm) { _midiParser = MidiParser::createParser_SMF(); // Create the driver - MidiDriverType driver = detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - _driver = createMidi(driver); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); + _driver = createMidi(dev); this->open(); // Set the parser's driver @@ -702,20 +716,64 @@ bool MusicPlayerMac::load(uint32 fileref, bool loop) { Common::SeekableReadStream *file = _vm->_macResFork->getResource(MKID_BE('cmid'), fileref & 0x3FF); if (file) { - // TODO: A form of LZSS, not supported by the current Groovie decoder. - // The offset/length uint16 is BE, but not sure the amount of length bits - // nor whether the offset is absolute/relative. - warning("TODO: Mac Compressed MIDI: cmid 0x%04x", fileref & 0x3FF); + // Found the resource, decompress it + Common::SeekableReadStream *tmp = decompressMidi(file); delete file; - return false; + file = tmp; + } else { + // Otherwise, it's uncompressed + file = _vm->_macResFork->getResource(MKID_BE('Midi'), fileref & 0x3FF); + if (!file) + error("Groovie::Music: Couldn't find resource 0x%04X", fileref); } - // Otherwise, it's uncompressed - file = _vm->_macResFork->getResource(MKID_BE('Midi'), fileref & 0x3FF); - if (!file) - error("Groovie::Music: Couldn't find resource 0x%04X", fileref); - return loadParser(file, loop); } +Common::SeekableReadStream *MusicPlayerMac::decompressMidi(Common::SeekableReadStream *stream) { + // Initialize an output buffer of the given size + uint32 size = stream->readUint32BE(); + byte *output = (byte *)malloc(size); + + byte *current = output; + uint32 decompBytes = 0; + while ((decompBytes < size) && !stream->eos()) { + // 8 flags + byte flags = stream->readByte(); + + for (byte i = 0; (i < 8) && !stream->eos(); i++) { + if (flags & 1) { + // 1: Next byte is a literal + *(current++) = stream->readByte(); + if (stream->eos()) + continue; + decompBytes++; + } else { + // 0: It's a reference to part of the history + uint16 args = stream->readUint16BE(); + if (stream->eos()) + continue; + + // Length = 4bit unsigned (3 minimal) + uint8 length = (args >> 12) + 3; + + // Offset = 12bit signed (all values are negative) + int16 offset = (args & 0xFFF) | 0xF000; + + // Copy from the past decompressed bytes + decompBytes += length; + while (length > 0) { + *(current) = *(current + offset); + current++; + length--; + } + } + flags = flags >> 1; + } + } + + // Return the output buffer wrapped in a MemoryReadStream + return new Common::MemoryReadStream(output, size, DisposeAfterUse::YES); +} + } // End of Groovie namespace diff --git a/engines/groovie/music.h b/engines/groovie/music.h index 2feef9cbf7..5b5f5bd346 100644 --- a/engines/groovie/music.h +++ b/engines/groovie/music.h @@ -161,6 +161,9 @@ public: protected: bool load(uint32 fileref, bool loop); + +private: + Common::SeekableReadStream *decompressMidi(Common::SeekableReadStream *stream); }; } // End of Groovie namespace diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp index 297da6ccc2..9fd7fa7d63 100644 --- a/engines/groovie/script.cpp +++ b/engines/groovie/script.cpp @@ -86,11 +86,11 @@ Script::Script(GroovieEngine *vm, EngineVersion version) : } // Initialize the music type variable - int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - if (midiDriver == MD_ADLIB) { + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); + if (MidiDriver::getMusicType(dev) == MT_ADLIB) { // MIDI through AdLib setVariable(0x100, 0); - } else if ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")) { + } else if ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")) { // MT-32 setVariable(0x100, 2); } else { diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 6e9359e7fc..f3e6c7c8cc 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -41,1172 +41,7 @@ struct KYRAGameDescription { Kyra::GameFlags flags; }; -namespace { - -#define FLAGS(x, y, z, a, b, c, d, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, d, id } -#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, d, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, d, id } - -#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA1) -#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, true, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_DEMO_CD_FLAGS FLAGS(true, true, true, false, false, false, false, Kyra::GI_KYRA1) - -#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA2) -#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, true, false, false, false, Kyra::GI_KYRA2) - -#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, false, true, true, Kyra::GI_KYRA3) -#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, false, true, false, Kyra::GI_KYRA3) -#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, true, false, Kyra::GI_KYRA3) - -#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_LOL) -#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_LOL) -#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_LOL) -#define LOL_PC98_SJIS_FLAGS FLAGS(false, false, false, true, true, false, false, Kyra::GI_LOL) -#define LOL_DEMO_FLAGS FLAGS(true, true, false, false, false, false, false, Kyra::GI_LOL) -#define LOL_KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2) - -const KYRAGameDescription adGameDescs[] = { - /* disable these targets until they get supported - { - { - "kyra1", - 0, - AD_ENTRY1("DISK1.EXE", "c8641d0414d6c966d0a3dad79db07bf4"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_CMP_FLAGS - }, - - { - { - "kyra1", - 0, - AD_ENTRY1("DISK1.EXE", "5d5cee4c3d0b68d586788b74243d254a"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_CMP_FLAGS - }, - */ - - { - { - "kyra1", - "Extracted", - AD_ENTRY1("GEMCUT.EMC", "3c244298395520bb62b5edfe41688879"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_FLAGS - }, - { - { - "kyra1", - "Extracted", - AD_ENTRY1("GEMCUT.EMC", "796e44863dd22fa635b042df1bf16673"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_FLAGS - }, - { - { - "kyra1", - "Extracted", - AD_ENTRY1("GEMCUT.EMC", "abf8eb360e79a6c2a837751fbd4d3d24"), - Common::FR_FRA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_FLAGS - }, - { - { - "kyra1", - "Extracted", - AD_ENTRY1("GEMCUT.EMC", "6018e1dfeaca7fe83f8d0b00eb0dd049"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_FLAGS - }, - { // from Arne.F - { - "kyra1", - "Extracted", - AD_ENTRY1("GEMCUT.EMC", "f0b276781f47c130f423ec9679fe9ed9"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_FLAGS - }, - { // from VooD - { - "kyra1", - "Extracted", - AD_ENTRY1("GEMCUT.EMC", "8909b41596913b3f5deaf3c9f1017b01"), - Common::ES_ESP, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_FLAGS - }, - { // floppy 1.8 from clemmy - { - "kyra1", - "Extracted", - AD_ENTRY1("GEMCUT.EMC", "747861d2a9c643c59fdab570df5b9093"), - Common::ES_ESP, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_FLAGS - }, - { // from gourry - { - "kyra1", - "Extracted", - AD_ENTRY1("GEMCUT.EMC", "ef08c8c237ee1473fd52578303fc36df"), - Common::IT_ITA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_FLAGS - }, - - { - { - "kyra1", - 0, - { - { "GEMCUT.PAK", 0, "2bd1da653eaefd691e050e4a9eb68a64", -1 }, - { "GEMCUT.EMC", 0, "2a3f44e179f1e9f7643e90083c747571", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::EN_ANY, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_AMIGA_FLAGS - }, - - { - { - "kyra1", - 0, - { - { "GEMCUT.PAK", 0, "2bd1da653eaefd691e050e4a9eb68a64", -1 }, - { "GEMCUT.EMC", 0, "74f99e9ed99abf8d0429826d78485a2a", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::DE_DEU, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_AMIGA_FLAGS - }, - - { - { - "kyra1", - 0, - { - { "GEMCUT.EMC", 0, "796e44863dd22fa635b042df1bf16673", -1 }, - { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::EN_ANY, - Common::kPlatformMacintosh, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_FLAGS - }, - - { // FM-TOWNS version - { - "kyra1", - 0, - { - { "EMC.PAK", 0, "a046bb0b422061aab8e4c4689400343a", -1 }, - { "TWMUSIC.PAK", 0, "e53bca3a3e3fb49107d59463ec387a59", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::EN_ANY, - Common::kPlatformFMTowns, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_TOWNS_FLAGS - }, - { - { - "kyra1", - 0, - { - { "JMC.PAK", 0, "9c5707a2a478e8167e44283246612d2c", -1 }, - { "TWMUSIC.PAK", 0, "e53bca3a3e3fb49107d59463ec387a59", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::JA_JPN, - Common::kPlatformFMTowns, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_TOWNS_SJIS_FLAGS - }, - - // PC-9801 floppy + CD / PC-9821 floppy version are all using the same data files, - // thus we will mark it as non CD game. - { - { - "kyra1", - "", - { - { "JMC.PAK", 0, "9c5707a2a478e8167e44283246612d2c", -1 }, - { "MUSIC98.PAK", 0, "02fc212f799331b769b274e33d87b37f", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::JA_JPN, - Common::kPlatformPC98, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_TOWNS_SJIS_FLAGS - }, - - { - { - "kyra1", - "CD", - AD_ENTRY1("GEMCUT.PAK", "fac399fe62f98671e56a005c5e94e39f"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_CD, - Common::GUIO_NONE - }, - KYRA1_CD_FLAGS - }, - { - { - "kyra1", - "CD", - AD_ENTRY1("GEMCUT.PAK", "230f54e6afc007ab4117159181a1c722"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_CD, - Common::GUIO_NONE - }, - KYRA1_CD_FLAGS - }, - { - { - "kyra1", - "CD", - AD_ENTRY1("GEMCUT.PAK", "b037c41768b652a040360ffa3556fd2a"), - Common::FR_FRA, - Common::kPlatformPC, - ADGF_CD, - Common::GUIO_NONE - }, - KYRA1_CD_FLAGS - }, - - { // italian fan translation see fr#1727941 "KYRA: add Italian CD Version to kyra.dat" - { - "kyra1", - "CD", - AD_ENTRY1("GEMCUT.PAK", "d8327fc4b7a72b23c900fa13aef4093a"), - Common::IT_ITA, - Common::kPlatformPC, - ADGF_CD, - Common::GUIO_NONE - }, - KYRA1_CD_FLAGS - }, - - { // Kyra 1 Mac CD as mentioned in fr #2766454 "KYRA1: Add support for Macintosh CD" by nnooiissee - { - "kyra1", - "CD", - { - { "GEMCUT.PAK", 0, "d3d4b281cd357230aabcec46843d04bd", -1 }, - { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::EN_ANY, - Common::kPlatformMacintosh, - ADGF_CD, - Common::GUIO_NONE - }, - KYRA1_CD_FLAGS - }, - { - { - "kyra1", - "CD", - { - { "GEMCUT.PAK", 0, "4a0cb720e824295bcbccbd1407652110", -1 }, - { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::DE_DEU, - Common::kPlatformMacintosh, - ADGF_CD, - Common::GUIO_NONE - }, - KYRA1_CD_FLAGS - }, - { - { - "kyra1", - "CD", - { - { "GEMCUT.PAK", 0, "b71ee090aa12e80ed2ba068826d92bed", -1 }, - { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::FR_FRA, - Common::kPlatformMacintosh, - ADGF_CD, - Common::GUIO_NONE - }, - KYRA1_CD_FLAGS - }, - - { - { - "kyra1", - "Demo", - AD_ENTRY1("DEMO1.WSA", "fb722947d94897512b13b50cc84fd648"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO, - Common::GUIO_NOSPEECH - }, - KYRA1_DEMO_FLAGS - }, - - { // Special Kyrandia 1 CD demo - { - "kyra1", - "Demo/CD", - AD_ENTRY1("INTRO.VRM", "e3045fb69b8c29db84b8fda3ccbdac54"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO | ADGF_CD, - Common::GUIO_NONE - }, - KYRA1_DEMO_CD_FLAGS - }, - - { // Floppy version - { - "kyra2", - 0, - AD_ENTRY1("WESTWOOD.001", "3f52dda68c4f7696c8309038be9f4151"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA2_FLOPPY_CMP_FLAGS - }, - - { // Floppy version - { - "kyra2", - 0, - AD_ENTRY1("WESTWOOD.001", "d787b9559afddfe058b84c0b3a787224"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA2_FLOPPY_CMP_FLAGS - }, - - { // Floppy version extracted - { - "kyra2", - "Extracted", - AD_ENTRY1("FATE.PAK", "1ba18be685ad8e5a0ab5d46a0ce4d345"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA2_FLOPPY_FLAGS - }, - - { // Floppy version extracted - { - "kyra2", - "Extracted", - AD_ENTRY1("FATE.PAK", "262fb69dd8e52e596c7aefc6456f7c1b"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA2_FLOPPY_FLAGS - }, - - { // Floppy version extracted - { - "kyra2", - "Extracted", - AD_ENTRY1("FATE.PAK", "f7de11506b4c8fdf64bc763206c3e4e7"), - Common::FR_FRA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA2_FLOPPY_FLAGS - }, - - { // Floppy version extracted - { - "kyra2", - "Extracted", - AD_ENTRY1("FATE.PAK", "e0a70c31b022cb4bb3061890020fc27c"), - Common::IT_ITA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA2_FLOPPY_FLAGS - }, - - { // CD version - { - "kyra2", - "CD", - AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - KYRA2_CD_FLAGS - }, - { - { - "kyra2", - "CD", - AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - KYRA2_CD_FLAGS - }, - { - { - "kyra2", - "CD", - AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - KYRA2_CD_FLAGS - }, - - // Italian fan translation, see fr#2003504 "KYRA: add support for Italian version of Kyrandia 2&3" - { // CD version - { - "kyra2", - "CD", - AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"), - Common::IT_ITA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) - }, - { - { - "kyra2", - "CD", - AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) - }, - { - { - "kyra2", - "CD", - AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"), - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) - }, - - { - { - "kyra2", - "CD", - AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"), - Common::IT_ITA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) - }, - - { - { - "kyra2", - "CD", - AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) - }, - - { - { - "kyra2", - "CD", - AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"), - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) - }, - - { // Interactive Demo - { - "kyra2", - "CD/Demo", - AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO, - Common::GUIO_NONE - }, - KYRA2_CD_DEMO_FLAGS - }, - - { // Interactive Demo - { - "kyra2", - "CD/Demo", - AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO, - Common::GUIO_NONE - }, - KYRA2_CD_DEMO_FLAGS - }, - - { // Interactive Demo - { - "kyra2", - "CD/Demo", - AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"), - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO, - Common::GUIO_NONE - }, - KYRA2_CD_DEMO_FLAGS - }, - - { // Non-Interactive Demos - { - "kyra2", - "Demo", - AD_ENTRY1("VOC.PAK", "ecb3561b63749158172bf21528cf5f45"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO, - Common::GUIO_NONE - }, - KYRA2_DEMO_FLAGS - }, - - { // FM-TOWNS - { - "kyra2", - 0, - AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), - Common::EN_ANY, - Common::kPlatformFMTowns, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA2_TOWNS_FLAGS - }, - { - { - "kyra2", - 0, - AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), - Common::JA_JPN, - Common::kPlatformFMTowns, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA2_TOWNS_SJIS_FLAGS - }, - { // PC-9821 - { - "kyra2", - "CD", - AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), - Common::EN_ANY, - Common::kPlatformPC98, - ADGF_CD, - Common::GUIO_NOSPEECH - }, - KYRA2_TOWNS_FLAGS - }, - { - { - "kyra2", - "CD", - AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), - Common::JA_JPN, - Common::kPlatformPC98, - ADGF_CD, - Common::GUIO_NOSPEECH - }, - KYRA2_TOWNS_SJIS_FLAGS - }, - - // Kyra3 - - // non installed version - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, - { "WESTWOOD.001", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_FLAGS - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, - { "WESTWOOD.001", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_FLAGS - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, - { "WESTWOOD.001", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_FLAGS - }, - - // installed version - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_INS_FLAGS - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_INS_FLAGS - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_INS_FLAGS - }, - - // Mac version - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformMacintosh, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_INS_FLAGS - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::DE_DEU, - Common::kPlatformMacintosh, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_INS_FLAGS - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::FR_FRA, - Common::kPlatformMacintosh, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_INS_FLAGS - }, - - // Spanish fan translation, see fr#1994040 "KYRA3: Add support for Spanish fan translation" - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::ES_ESP, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) - }, - - // Italian fan translation, see fr#2003504 "KYRA: add support for Italian version of Kyrandia 2&3" - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA) - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA) - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::IT_ITA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA) - }, - -#ifdef ENABLE_LOL - // Lands of Lore CD - { - { - "lol", - "CD", - { - { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 }, - { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - LOL_CD_FLAGS - }, - - { - { - "lol", - "CD", - { - { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 }, - { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, - { 0, 0, 0, 0 } - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - LOL_CD_FLAGS - }, - - { - { - "lol", - "CD", - { - { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 }, - { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, - { 0, 0, 0, 0 } - }, - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - LOL_CD_FLAGS - }, - - { - { - "lol", - "CD", - { - { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 }, - { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - LOL_CD_FLAGS - }, - - { - { - "lol", - "CD", - { - { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 }, - { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, - { 0, 0, 0, 0 } - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - LOL_CD_FLAGS - }, - - { - { - "lol", - "CD", - { - { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 }, - { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, - { 0, 0, 0, 0 } - }, - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - LOL_CD_FLAGS - }, - - { - { - "lol", - 0, - { - { "WESTWOOD.1", 0, "c656aa9a2b4032d341e3dc8e3525b917", -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - LOL_FLOPPY_CMP_FLAGS - }, - - { - { - "lol", - 0, - { - { "WESTWOOD.1", 0, "3c61cb7de5b2ec452f5851f5075207ee", -1 }, - { 0, 0, 0, 0 } - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - LOL_FLOPPY_CMP_FLAGS - }, - - { - { - "lol", - "Extracted", - { - { "GENERAL.PAK", 0, "2aaa30e120c08af87196820e9dd4bf73", -1 }, - { "CHAPTER7.PAK", 0, "eb92bf7ebb4e890add1233a6b0c810ff", -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - LOL_FLOPPY_FLAGS - }, - - { - { - "lol", - "Extracted", - { - { "GENERAL.PAK", 0, "996e66e81054d36249907a1d8158da3d", -1 }, - { "CHAPTER7.PAK", 0, "cabee57f00d6d84b65a732b6868a4959", -1 }, - { 0, 0, 0, 0 } - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - LOL_FLOPPY_FLAGS - }, - - { - { - "lol", - 0, - { - { "GENERAL.PAK", 0, "3fe6539b9b09084c0984eaf7170464e9", -1 }, - { "MUS.PAK", 0, "008dc69d8cbcdb6bae30e270fab26e76", -1 }, - { 0, 0, 0, 0 } - }, - Common::JA_JPN, - Common::kPlatformPC98, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - LOL_PC98_SJIS_FLAGS - }, - - { - { - "lol", - "Demo", - { - { "INTRO.PAK", 0, "4bc22a3b57f19a49212c5de58ab014d6", -1 }, - { "INTROVOC.PAK", 0, "7e578e4f1da31c1f294e14a8e8f3cc44", -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO, - Common::GUIO_NONE - }, - LOL_DEMO_FLAGS - }, - - { - { - "lol", - "Demo", - { - { "GENERAL.PAK", 0, "e94863d86c4597a2d581d05481c152ba", -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO, - Common::GUIO_NOSPEECH - }, - LOL_KYRA2_DEMO_FLAGS - }, -#endif // ENABLE_LOL - - { AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0, 0) } -}; - -const PlainGameDescriptor gameList[] = { - { "kyra1", "The Legend of Kyrandia" }, - { "kyra2", "The Legend of Kyrandia: The Hand of Fate" }, - { "kyra3", "The Legend of Kyrandia: Malcolm's Revenge" }, -#ifdef ENABLE_LOL - { "lol", "Lands of Lore: The Throne of Chaos" }, -#endif // ENABLE_LOL - { 0, 0 } -}; +#include "kyra/detection_tables.h" const ADParams detectionParams = { // Pointer to ADGameDescription or its superset structure @@ -1226,11 +61,13 @@ const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NONE + Common::GUIO_NONE, + // Maximum directory depth + 1, + // List of directory globs + 0 }; -} // End of anonymous namespace - class KyraMetaEngine : public AdvancedMetaEngine { public: KyraMetaEngine() : AdvancedMetaEngine(detectionParams) {} diff --git a/engines/kyra/detection_tables.h b/engines/kyra/detection_tables.h new file mode 100644 index 0000000000..390281c356 --- /dev/null +++ b/engines/kyra/detection_tables.h @@ -0,0 +1,1192 @@ +/* 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$ + */ + +namespace { + +#define FLAGS(x, y, z, a, b, c, d, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, d, id } +#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, d, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, d, id } + +#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA1) +#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, true, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_DEMO_CD_FLAGS FLAGS(true, true, true, false, false, false, false, Kyra::GI_KYRA1) + +#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA2) +#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, true, false, false, false, Kyra::GI_KYRA2) + +#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, false, true, true, Kyra::GI_KYRA3) +#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, false, true, false, Kyra::GI_KYRA3) +#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, true, false, Kyra::GI_KYRA3) + +#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_LOL) +#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_LOL) +#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_LOL) +#define LOL_PC98_SJIS_FLAGS FLAGS(false, false, false, true, true, false, false, Kyra::GI_LOL) +#define LOL_DEMO_FLAGS FLAGS(true, true, false, false, false, false, false, Kyra::GI_LOL) +#define LOL_KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2) + +const KYRAGameDescription adGameDescs[] = { + /* disable these targets until they get supported + { + { + "kyra1", + 0, + AD_ENTRY1("DISK1.EXE", "c8641d0414d6c966d0a3dad79db07bf4"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK + }, + KYRA1_FLOPPY_CMP_FLAGS + }, + + { + { + "kyra1", + 0, + AD_ENTRY1("DISK1.EXE", "5d5cee4c3d0b68d586788b74243d254a"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK + }, + KYRA1_FLOPPY_CMP_FLAGS + }, + */ + + { + { + "kyra1", + "Extracted", + AD_ENTRY1("GEMCUT.EMC", "3c244298395520bb62b5edfe41688879"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK + }, + KYRA1_FLOPPY_FLAGS + }, + { + { + "kyra1", + "Extracted", + AD_ENTRY1("GEMCUT.EMC", "796e44863dd22fa635b042df1bf16673"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK + }, + KYRA1_FLOPPY_FLAGS + }, + { + { + "kyra1", + "Extracted", + AD_ENTRY1("GEMCUT.EMC", "abf8eb360e79a6c2a837751fbd4d3d24"), + Common::FR_FRA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK + }, + KYRA1_FLOPPY_FLAGS + }, + { + { + "kyra1", + "Extracted", + AD_ENTRY1("GEMCUT.EMC", "6018e1dfeaca7fe83f8d0b00eb0dd049"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK + }, + KYRA1_FLOPPY_FLAGS + }, + { // from Arne.F + { + "kyra1", + "Extracted", + AD_ENTRY1("GEMCUT.EMC", "f0b276781f47c130f423ec9679fe9ed9"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK + }, + KYRA1_FLOPPY_FLAGS + }, + { // from VooD + { + "kyra1", + "Extracted", + AD_ENTRY1("GEMCUT.EMC", "8909b41596913b3f5deaf3c9f1017b01"), + Common::ES_ESP, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK + }, + KYRA1_FLOPPY_FLAGS + }, + { // floppy 1.8 from clemmy + { + "kyra1", + "Extracted", + AD_ENTRY1("GEMCUT.EMC", "747861d2a9c643c59fdab570df5b9093"), + Common::ES_ESP, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK + }, + KYRA1_FLOPPY_FLAGS + }, + { // from gourry + { + "kyra1", + "Extracted", + AD_ENTRY1("GEMCUT.EMC", "ef08c8c237ee1473fd52578303fc36df"), + Common::IT_ITA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK + }, + KYRA1_FLOPPY_FLAGS + }, + + { + { + "kyra1", + 0, + { + { "GEMCUT.PAK", 0, "2bd1da653eaefd691e050e4a9eb68a64", -1 }, + { "GEMCUT.EMC", 0, "2a3f44e179f1e9f7643e90083c747571", -1 }, + { NULL, 0, NULL, 0 } + }, + Common::EN_ANY, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_AMIGA_FLAGS + }, + + { + { + "kyra1", + 0, + { + { "GEMCUT.PAK", 0, "2bd1da653eaefd691e050e4a9eb68a64", -1 }, + { "GEMCUT.EMC", 0, "74f99e9ed99abf8d0429826d78485a2a", -1 }, + { NULL, 0, NULL, 0 } + }, + Common::DE_DEU, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_AMIGA_FLAGS + }, + + { + { + "kyra1", + 0, + { + { "GEMCUT.EMC", 0, "796e44863dd22fa635b042df1bf16673", -1 }, + { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 }, + { NULL, 0, NULL, 0 } + }, + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_FLOPPY_FLAGS + }, + + { // FM-TOWNS version + { + "kyra1", + 0, + { + { "EMC.PAK", 0, "a046bb0b422061aab8e4c4689400343a", -1 }, + { "TWMUSIC.PAK", 0, "e53bca3a3e3fb49107d59463ec387a59", -1 }, + { NULL, 0, NULL, 0 } + }, + Common::EN_ANY, + Common::kPlatformFMTowns, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDITOWNS + }, + KYRA1_TOWNS_FLAGS + }, + { + { + "kyra1", + 0, + { + { "JMC.PAK", 0, "9c5707a2a478e8167e44283246612d2c", -1 }, + { "TWMUSIC.PAK", 0, "e53bca3a3e3fb49107d59463ec387a59", -1 }, + { NULL, 0, NULL, 0 } + }, + Common::JA_JPN, + Common::kPlatformFMTowns, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDITOWNS + }, + KYRA1_TOWNS_SJIS_FLAGS + }, + + // PC-9801 floppy + CD / PC-9821 floppy version are all using the same data files, + // thus we will mark it as non CD game. + { + { + "kyra1", + "", + { + { "JMC.PAK", 0, "9c5707a2a478e8167e44283246612d2c", -1 }, + { "MUSIC98.PAK", 0, "02fc212f799331b769b274e33d87b37f", -1 }, + { NULL, 0, NULL, 0 } + }, + Common::JA_JPN, + Common::kPlatformPC98, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIPC98 + }, + KYRA1_TOWNS_SJIS_FLAGS + }, + + { + { + "kyra1", + "CD", + AD_ENTRY1("GEMCUT.PAK", "fac399fe62f98671e56a005c5e94e39f"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK + }, + KYRA1_CD_FLAGS + }, + { + { + "kyra1", + "CD", + AD_ENTRY1("GEMCUT.PAK", "230f54e6afc007ab4117159181a1c722"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK + }, + KYRA1_CD_FLAGS + }, + { + { + "kyra1", + "CD", + AD_ENTRY1("GEMCUT.PAK", "b037c41768b652a040360ffa3556fd2a"), + Common::FR_FRA, + Common::kPlatformPC, + ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK + }, + KYRA1_CD_FLAGS + }, + + { // italian fan translation see fr#1727941 "KYRA: add Italian CD Version to kyra.dat" + { + "kyra1", + "CD", + AD_ENTRY1("GEMCUT.PAK", "d8327fc4b7a72b23c900fa13aef4093a"), + Common::IT_ITA, + Common::kPlatformPC, + ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK + }, + KYRA1_CD_FLAGS + }, + + { // Kyra 1 Mac CD as mentioned in fr #2766454 "KYRA1: Add support for Macintosh CD" by nnooiissee + { + "kyra1", + "CD", + { + { "GEMCUT.PAK", 0, "d3d4b281cd357230aabcec46843d04bd", -1 }, + { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 }, + { NULL, 0, NULL, 0 } + }, + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_CD, + Common::GUIO_NONE + }, + KYRA1_CD_FLAGS + }, + { + { + "kyra1", + "CD", + { + { "GEMCUT.PAK", 0, "4a0cb720e824295bcbccbd1407652110", -1 }, + { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 }, + { NULL, 0, NULL, 0 } + }, + Common::DE_DEU, + Common::kPlatformMacintosh, + ADGF_CD, + Common::GUIO_NONE + }, + KYRA1_CD_FLAGS + }, + { + { + "kyra1", + "CD", + { + { "GEMCUT.PAK", 0, "b71ee090aa12e80ed2ba068826d92bed", -1 }, + { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 }, + { NULL, 0, NULL, 0 } + }, + Common::FR_FRA, + Common::kPlatformMacintosh, + ADGF_CD, + Common::GUIO_NONE + }, + KYRA1_CD_FLAGS + }, + + { + { + "kyra1", + "Demo", + AD_ENTRY1("DEMO1.WSA", "fb722947d94897512b13b50cc84fd648"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DEMO, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK + }, + KYRA1_DEMO_FLAGS + }, + + { // Special Kyrandia 1 CD demo + { + "kyra1", + "Demo/CD", + AD_ENTRY1("INTRO.VRM", "e3045fb69b8c29db84b8fda3ccbdac54"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DEMO | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK + }, + KYRA1_DEMO_CD_FLAGS + }, + + { // Floppy version + { + "kyra2", + 0, + AD_ENTRY1("WESTWOOD.001", "3f52dda68c4f7696c8309038be9f4151"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_FLOPPY_CMP_FLAGS + }, + + { // Floppy version + { + "kyra2", + 0, + AD_ENTRY1("WESTWOOD.001", "d787b9559afddfe058b84c0b3a787224"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_FLOPPY_CMP_FLAGS + }, + + { // Floppy version extracted + { + "kyra2", + "Extracted", + AD_ENTRY1("FATE.PAK", "1ba18be685ad8e5a0ab5d46a0ce4d345"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_FLOPPY_FLAGS + }, + + { // Floppy version extracted + { + "kyra2", + "Extracted", + AD_ENTRY1("FATE.PAK", "262fb69dd8e52e596c7aefc6456f7c1b"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_FLOPPY_FLAGS + }, + + { // Floppy version extracted + { + "kyra2", + "Extracted", + AD_ENTRY1("FATE.PAK", "f7de11506b4c8fdf64bc763206c3e4e7"), + Common::FR_FRA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_FLOPPY_FLAGS + }, + + { // Floppy version extracted + { + "kyra2", + "Extracted", + AD_ENTRY1("FATE.PAK", "e0a70c31b022cb4bb3061890020fc27c"), + Common::IT_ITA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_FLOPPY_FLAGS + }, + + { // CD version + { + "kyra2", + "CD", + AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_CD_FLAGS + }, + { + { + "kyra2", + "CD", + AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_CD_FLAGS + }, + { + { + "kyra2", + "CD", + AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_CD_FLAGS + }, + + // Italian fan translation, see fr#2003504 "KYRA: add support for Italian version of Kyrandia 2&3" + { // CD version + { + "kyra2", + "CD", + AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"), + Common::IT_ITA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) + }, + { + { + "kyra2", + "CD", + AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) + }, + { + { + "kyra2", + "CD", + AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"), + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) + }, + + { + { + "kyra2", + "CD", + AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"), + Common::IT_ITA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) + }, + + { + { + "kyra2", + "CD", + AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) + }, + + { + { + "kyra2", + "CD", + AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"), + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) + }, + + { // Interactive Demo + { + "kyra2", + "CD/Demo", + AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_CD_DEMO_FLAGS + }, + + { // Interactive Demo + { + "kyra2", + "CD/Demo", + AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_CD_DEMO_FLAGS + }, + + { // Interactive Demo + { + "kyra2", + "CD/Demo", + AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"), + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_CD_DEMO_FLAGS + }, + + { // Non-Interactive Demos + { + "kyra2", + "Demo", + AD_ENTRY1("VOC.PAK", "ecb3561b63749158172bf21528cf5f45"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DEMO, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + KYRA2_DEMO_FLAGS + }, + + { // FM-TOWNS + { + "kyra2", + 0, + AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), + Common::EN_ANY, + Common::kPlatformFMTowns, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDITOWNS + }, + KYRA2_TOWNS_FLAGS + }, + { + { + "kyra2", + 0, + AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), + Common::JA_JPN, + Common::kPlatformFMTowns, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDITOWNS + }, + KYRA2_TOWNS_SJIS_FLAGS + }, + { // PC-9821 + { + "kyra2", + "CD", + AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), + Common::EN_ANY, + Common::kPlatformPC98, + ADGF_CD, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIPC98 + }, + KYRA2_TOWNS_FLAGS + }, + { + { + "kyra2", + "CD", + AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), + Common::JA_JPN, + Common::kPlatformPC98, + ADGF_CD, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIPC98 + }, + KYRA2_TOWNS_SJIS_FLAGS + }, + + // Kyra3 + + // non installed version + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "WESTWOOD.001", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_FLAGS + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "WESTWOOD.001", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_FLAGS + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "WESTWOOD.001", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_FLAGS + }, + + // installed version + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_INS_FLAGS + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_INS_FLAGS + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_INS_FLAGS + }, + + // Mac version + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_INS_FLAGS + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformMacintosh, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_INS_FLAGS + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::FR_FRA, + Common::kPlatformMacintosh, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_INS_FLAGS + }, + + // Spanish fan translation, see fr#1994040 "KYRA3: Add support for Spanish fan translation" + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::ES_ESP, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) + }, + + // Italian fan translation, see fr#2003504 "KYRA: add support for Italian version of Kyrandia 2&3" + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA) + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA) + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::IT_ITA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA) + }, + +#ifdef ENABLE_LOL + // Lands of Lore CD + { + { + "lol", + "CD", + { + { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 }, + { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + LOL_CD_FLAGS + }, + + { + { + "lol", + "CD", + { + { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 }, + { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + LOL_CD_FLAGS + }, + + { + { + "lol", + "CD", + { + { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 }, + { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, + { 0, 0, 0, 0 } + }, + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + LOL_CD_FLAGS + }, + + { + { + "lol", + "CD", + { + { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 }, + { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + LOL_CD_FLAGS + }, + + { + { + "lol", + "CD", + { + { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 }, + { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + LOL_CD_FLAGS + }, + + { + { + "lol", + "CD", + { + { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 }, + { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, + { 0, 0, 0, 0 } + }, + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + LOL_CD_FLAGS + }, + + { + { + "lol", + 0, + { + { "WESTWOOD.1", 0, "c656aa9a2b4032d341e3dc8e3525b917", -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + LOL_FLOPPY_CMP_FLAGS + }, + + { + { + "lol", + 0, + { + { "WESTWOOD.1", 0, "3c61cb7de5b2ec452f5851f5075207ee", -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + LOL_FLOPPY_CMP_FLAGS + }, + + { + { + "lol", + "Extracted", + { + { "GENERAL.PAK", 0, "2aaa30e120c08af87196820e9dd4bf73", -1 }, + { "CHAPTER7.PAK", 0, "eb92bf7ebb4e890add1233a6b0c810ff", -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + LOL_FLOPPY_FLAGS + }, + + { + { + "lol", + "Extracted", + { + { "GENERAL.PAK", 0, "996e66e81054d36249907a1d8158da3d", -1 }, + { "CHAPTER7.PAK", 0, "cabee57f00d6d84b65a732b6868a4959", -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + LOL_FLOPPY_FLAGS + }, + + { + { + "lol", + 0, + { + { "GENERAL.PAK", 0, "3fe6539b9b09084c0984eaf7170464e9", -1 }, + { "MUS.PAK", 0, "008dc69d8cbcdb6bae30e270fab26e76", -1 }, + { 0, 0, 0, 0 } + }, + Common::JA_JPN, + Common::kPlatformPC98, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH | Common::GUIO_MIDIPC98 + }, + LOL_PC98_SJIS_FLAGS + }, + + { + { + "lol", + "Demo", + { + { "INTRO.PAK", 0, "4bc22a3b57f19a49212c5de58ab014d6", -1 }, + { "INTROVOC.PAK", 0, "7e578e4f1da31c1f294e14a8e8f3cc44", -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DEMO, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + LOL_DEMO_FLAGS + }, + + { + { + "lol", + "Demo", + { + { "GENERAL.PAK", 0, "e94863d86c4597a2d581d05481c152ba", -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DEMO, + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK + }, + LOL_KYRA2_DEMO_FLAGS + }, +#endif // ENABLE_LOL + + { AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0, 0) } +}; + +const PlainGameDescriptor gameList[] = { + { "kyra1", "The Legend of Kyrandia" }, + { "kyra2", "The Legend of Kyrandia: The Hand of Fate" }, + { "kyra3", "The Legend of Kyrandia: Malcolm's Revenge" }, +#ifdef ENABLE_LOL + { "lol", "Lands of Lore: The Throne of Chaos" }, +#endif // ENABLE_LOL + { 0, 0 } +}; + +} // End of anonymous namespace diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 00b32425c2..abe13cec2b 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -105,8 +105,11 @@ Common::Error KyraEngine_v1::init() { _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); if (!_flags.useDigSound) { - // We prefer AdLib over MIDI, since generally AdLib is better supported - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_MIDI | MDT_ADLIB); + // We prefer AdLib over MIDI in Kyra 1, since it offers MT-32 support only, most users don't have a real + // MT-32/LAPC1/CM32L/CM64 device and AdLib sounds better than our incomplete MT-32 emulator and also better than + // MT-32/GM mapping. For Kyra 2 and LoL which have real GM tracks which sound better than AdLib tracks we prefer GM + // since most users have a GM compatible device. + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_PCSPK | MDT_MIDI | MDT_ADLIB | ((_flags.gameID == GI_KYRA2 || _flags.gameID == GI_LOL) ? MDT_PREFER_GM : 0)); if (_flags.platform == Common::kPlatformFMTowns) { if (_flags.gameID == GI_KYRA1) @@ -120,24 +123,24 @@ Common::Error KyraEngine_v1::init() { _sound = new SoundTownsPC98_v2(this, _mixer); } else if (_flags.platform == Common::kPlatformAmiga) { _sound = new SoundAmiga(this, _mixer); - } else if (midiDriver == MD_ADLIB) { + } else if (MidiDriver::getMusicType(dev) == MT_ADLIB) { _sound = new SoundAdLibPC(this, _mixer); } else { Sound::kType type; - if (midiDriver == MD_PCSPK) + if (MidiDriver::getMusicType(dev) == MT_PCSPK) type = Sound::kPCSpkr; - else if (midiDriver == MD_MT32 || ConfMan.getBool("native_mt32")) + else if (MidiDriver::getMusicType(dev) == MT_MT32 || ConfMan.getBool("native_mt32")) type = Sound::kMidiMT32; else type = Sound::kMidiGM; MidiDriver *driver = 0; - if (midiDriver == MD_PCSPK) { + if (MidiDriver::getMusicType(dev) == MT_PCSPK) { driver = new MidiDriver_PCSpeaker(_mixer); } else { - driver = MidiDriver::createMidi(midiDriver); + driver = MidiDriver::createMidi(dev); if (type == Sound::kMidiMT32) driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); } diff --git a/engines/kyra/sound_intern.h b/engines/kyra/sound_intern.h index f4aab4db29..a229dc310d 100644 --- a/engines/kyra/sound_intern.h +++ b/engines/kyra/sound_intern.h @@ -180,6 +180,8 @@ public: int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, bool isSfx) { return -1; } void playSoundEffect(uint8); + void updateVolumeSettings(); + protected: int _lastTrack; uint8 *_musicTrackData; @@ -207,6 +209,8 @@ public: int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, bool isSfx); void playSoundEffect(uint8 track); + void updateVolumeSettings(); + protected: Audio::AudioStream *_currentSFX; int _lastTrack; diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index b2c8c5fb4b..7a570b3100 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -23,7 +23,9 @@ * */ +#include "common/config-manager.h" #include "common/system.h" + #include "kyra/resource.h" #include "kyra/sound_intern.h" #include "kyra/screen.h" @@ -1355,7 +1357,7 @@ public: void setOutputLevel(); virtual void fadeStep(); - void reset(); + virtual void reset(); const uint8 _idFlag; @@ -1432,13 +1434,14 @@ public: void protect(); void restore(); + virtual void reset(); void fadeStep(); protected: void setOutputLevel(uint8 lvl); - bool control_f0_setInstr(uint8 para); + bool control_f0_setPatch(uint8 para); bool control_f1_setTotalLevel(uint8 para); bool control_f4_setAlgorithm(uint8 para); bool control_f9_loadCustomPatch(uint8 para); @@ -1458,6 +1461,7 @@ public: ~TownsPC98_OpnSfxChannel() {} void loadData(uint8 *data); + void reset(); }; class TownsPC98_OpnChannelPCM : public TownsPC98_OpnChannel { @@ -1490,9 +1494,12 @@ public: void nextTick(int32 *buffer, uint32 bufferSize); + void setVolumeIntern(int volA, int volB) { _volumeA = volA; _volumeB = volB; } + void setVolumeChannelMasks(int channelMaskA, int channelMaskB) { _volMaskA = channelMaskA; _volMaskB = channelMaskB; } + uint8 chanEnable() const { return _chanEnable; } private: - void updatesRegs(); + void updateRegs(); uint8 _updateRequestBuf[64]; int _updateRequest; @@ -1529,6 +1536,11 @@ private: uint8 **_reg; + uint16 _volumeA; + uint16 _volumeB; + int _volMaskA; + int _volMaskB; + bool _ready; }; @@ -1543,6 +1555,9 @@ public: void nextTick(int32 *buffer, uint32 bufferSize); + void setVolumeIntern(int volA, int volB) { _volumeA = volA; _volumeB = volB; } + void setVolumeChannelMasks(int channelMaskA, int channelMaskB) { _volMaskA = channelMaskA; _volMaskB = channelMaskB; } + private: struct RhtChannel { const uint8 *data; @@ -1578,6 +1593,11 @@ private: uint8 **_reg; + uint16 _volumeA; + uint16 _volumeB; + int _volMaskA; + int _volMaskB; + bool _ready; }; @@ -1604,20 +1624,27 @@ public: int getRate() const { return _mixer->getOutputRate(); } protected: - void generateTables(); - void toggleRegProtection(bool prot) { _regProtectionFlag = prot; } uint8 readSSGStatus() { return _ssg->chanEnable(); } virtual void timerCallbackA() = 0; virtual void timerCallbackB() = 0; + // The audio driver can store and apply two different audio settings + // (usually for music and sound effects). The channel mask will determine + // which channels get effected by the setting. The first bits will be + // the normal opn channels, the next bits the ssg channels and the final + // bit the rhythm channel. + void setVolumeIntern(int volA, int volB); + void setVolumeChannelMasks(int channelMaskA, int channelMaskB); + const int _numChan; const int _numSSG; const bool _hasPercussion; Common::Mutex _mutex; private: + void generateTables(); void nextTick(int32 *buffer, uint32 bufferSize); void generateOutput(int32 &leftSample, int32 &rightSample, int32 *del, int32 *feed); @@ -1670,6 +1697,9 @@ private: OpnTimer _timers[2]; + int _volMaskA, _volMaskB; + uint16 _volumeA, _volumeB; + const float _baserate; uint32 _timerbase; @@ -1709,6 +1739,9 @@ public: bool looping() { return _looping == _updateChannelsFlag ? true : false; } bool musicPlaying() { return _musicPlaying; } + void setMusicVolume(int volume) { _musicVolume = volume; setVolumeIntern(_musicVolume, _sfxVolume); } + void setSoundEffectVolume(int volume) { _sfxVolume = volume; setVolumeIntern(_musicVolume, _sfxVolume); } + protected: void startSoundEffect(); @@ -1751,6 +1784,9 @@ protected: uint8 *_sfxData; uint16 _sfxOffsets[2]; + uint16 _musicVolume; + uint16 _sfxVolume; + static const uint8 _drvTables[]; bool _ready; @@ -1823,33 +1859,23 @@ void TownsPC98_OpnChannel::loadData(uint8 *data) { _dataPtr = data; _totalLevel = 0x7F; - uint8 *src_b = _dataPtr; - int loop = 1; - uint8 cmd = 0; - while (loop) { - if (loop == 1) { - cmd = *src_b++; - if (cmd < 0xf0) { - src_b++; - loop = 1; - } else { - if (cmd == 0xff) { - loop = *src_b ? 2 : 0; - if (READ_LE_UINT16(src_b)) - _drv->_looping |= _idFlag; - } else if (cmd == 0xf6) { - loop = 3; - } else { - loop = 2; - } - } - } else if (loop == 2) { - src_b += _drv->_opnFxCmdLen[cmd - 240]; - loop = 1; - } else if (loop == 3) { - src_b[0] = src_b[1]; - src_b += 4; - loop = 1; + uint8 *tmp = _dataPtr; + for (bool loop = true; loop; ) { + uint8 cmd = *tmp++; + if (cmd < 0xf0) { + tmp++; + } else if (cmd == 0xff) { + if (READ_LE_UINT16(tmp)) { + _drv->_looping |= _idFlag; + tmp += _drv->_opnFxCmdLen[cmd - 240]; + } else + loop = false; + } else if (cmd == 0xf6) { + // reset repeat section countdown + tmp[0] = tmp[1]; + tmp += 4; + } else { + tmp += _drv->_opnFxCmdLen[cmd - 240]; } } } @@ -2178,7 +2204,7 @@ void TownsPC98_OpnChannelSSG::init() { #define Control(x) &TownsPC98_OpnChannelSSG::control_##x static const ControlEventFunc ctrlEventsSSG[] = { - Control(f0_setInstr), + Control(f0_setPatch), Control(f1_setTotalLevel), Control(f2_setKeyOffTime), Control(f3_setFreqLSB), @@ -2372,6 +2398,23 @@ void TownsPC98_OpnChannelSSG::setOutputLevel(uint8 lvl) { _drv->writeReg(_part, 8 + _regOffset, _ssgTl); } +void TownsPC98_OpnChannelSSG::reset() { + TownsPC98_OpnChannel::reset(); + + // Unlike the original we restore the default patch data. This fixes a bug + // where certain sound effects would bring each other out of tune (e.g. the + // dragon's fire in Darm's house in Kyra 1 would sound different each time + // you triggered another sfx by dropping an item etc.) + uint8 i = (10 + _regOffset) << 4; + const uint8 *src = &_drv->_drvTables[156]; + _drv->_ssgPatches[i] = src[i]; + _drv->_ssgPatches[i + 3] = src[i + 3]; + _drv->_ssgPatches[i + 4] = src[i + 4]; + _drv->_ssgPatches[i + 6] = src[i + 6]; + _drv->_ssgPatches[i + 8] = src[i + 8]; + _drv->_ssgPatches[i + 12] = src[i + 12]; +} + void TownsPC98_OpnChannelSSG::fadeStep() { _totalLevel--; if ((int8)_totalLevel < 0) @@ -2379,7 +2422,7 @@ void TownsPC98_OpnChannelSSG::fadeStep() { setOutputLevel(_ssgStartLvl); } -bool TownsPC98_OpnChannelSSG::control_f0_setInstr(uint8 para) { +bool TownsPC98_OpnChannelSSG::control_f0_setPatch(uint8 para) { _instr = para << 4; para = (para >> 3) & 0x1e; if (para) @@ -2463,6 +2506,39 @@ void TownsPC98_OpnSfxChannel::loadData(uint8 *data) { _dataPtr = data; _ssgTl = 0xff; _algorithm = 0x80; + + uint8 *tmp = _dataPtr; + for (bool loop = true; loop; ) { + uint8 cmd = *tmp++; + if (cmd < 0xf0) { + tmp++; + } else if (cmd == 0xff) { + loop = false; + } else if (cmd == 0xf6) { + // reset repeat section countdown + tmp[0] = tmp[1]; + tmp += 4; + } else { + tmp += _drv->_opnFxCmdLen[cmd - 240]; + } + } +} + +void TownsPC98_OpnSfxChannel::reset() { + TownsPC98_OpnChannel::reset(); + + // Unlike the original we restore the default patch data. This fixes a bug + // where certain sound effects would bring each other out of tune (e.g. the + // dragon's fire in Darm's house in Kyra 1 would sound different each time + // you triggered another sfx by dropping an item etc.) + uint8 i = (13 + _regOffset) << 4; + const uint8 *src = &_drv->_drvTables[156]; + _drv->_ssgPatches[i] = src[i]; + _drv->_ssgPatches[i + 3] = src[i + 3]; + _drv->_ssgPatches[i + 4] = src[i + 4]; + _drv->_ssgPatches[i + 6] = src[i + 6]; + _drv->_ssgPatches[i + 8] = src[i + 8]; + _drv->_ssgPatches[i + 12] = src[i + 12]; } TownsPC98_OpnChannelPCM::TownsPC98_OpnChannelPCM(TownsPC98_OpnDriver *driver, uint8 regOffs, @@ -2557,7 +2633,8 @@ bool TownsPC98_OpnChannelPCM::control_ff_endOfTrack(uint8 para) { TownsPC98_OpnSquareSineSource::TownsPC98_OpnSquareSineSource(const uint32 timerbase) : _tlTable(0), _tleTable(0), _updateRequest(-1), _tickLength(timerbase * 27), _ready(0), _reg(0), _rand(1), _outN(1), _nTick(0), _evpUpdateCnt(0), _evpTimer(0x1f), _pReslt(0x1f), _attack(0), _cont(false), _evpUpdate(true), - _timer(0), _noiseGenerator(0), _chanEnable(0) { + _timer(0), _noiseGenerator(0), _chanEnable(0), + _volMaskA(0), _volMaskB(0), _volumeA(Audio::Mixer::kMaxMixerVolume), _volumeB(Audio::Mixer::kMaxMixerVolume) { memset(_channels, 0, sizeof(_channels)); memset(_updateRequestBuf, 0, sizeof(_updateRequestBuf)); @@ -2705,24 +2782,30 @@ void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) { } } _pReslt = _evpTimer ^ _attack; - updatesRegs(); + updateRegs(); } int32 finOut = 0; for (int ii = 0; ii < 3; ii++) { - if ((_channels[ii].vol >> 4) & 1) - finOut += _tleTable[_channels[ii].out ? _pReslt : 0]; - else - finOut += _tlTable[_channels[ii].out ? (_channels[ii].vol & 0x0f) : 0]; + int32 finOutTemp = ((_channels[ii].vol >> 4) & 1) ? _tleTable[_channels[ii].out ? _pReslt : 0] : _tlTable[_channels[ii].out ? (_channels[ii].vol & 0x0f) : 0]; + + if ((1 << ii) & _volMaskA) + finOutTemp = (finOutTemp * _volumeA) / Audio::Mixer::kMaxMixerVolume; + + if ((1 << ii) & _volMaskB) + finOutTemp = (finOutTemp * _volumeB) / Audio::Mixer::kMaxMixerVolume; + + finOut += finOutTemp; } - finOut /= 3; + finOut /= 3; + buffer[i << 1] += finOut; buffer[(i << 1) + 1] += finOut; } } -void TownsPC98_OpnSquareSineSource::updatesRegs() { +void TownsPC98_OpnSquareSineSource::updateRegs() { for (int i = 0; i < _updateRequest;) { uint8 b = _updateRequestBuf[i++]; uint8 a = _updateRequestBuf[i++]; @@ -2732,7 +2815,7 @@ void TownsPC98_OpnSquareSineSource::updatesRegs() { } TownsPC98_OpnPercussionSource::TownsPC98_OpnPercussionSource(const uint32 timerbase) : - _tickLength(timerbase * 2), _timer(0), _ready(false) { + _tickLength(timerbase * 2), _timer(0), _ready(false), _volMaskA(0), _volMaskB(0), _volumeA(Audio::Mixer::kMaxMixerVolume), _volumeB(Audio::Mixer::kMaxMixerVolume) { memset(_rhChan, 0, sizeof(RhtChannel) * 6); _reg = new uint8 *[40]; @@ -2891,6 +2974,12 @@ void TownsPC98_OpnPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) { finOut <<= 1; + if (1 & _volMaskA) + finOut = (finOut * _volumeA) / Audio::Mixer::kMaxMixerVolume; + + if (1 & _volMaskB) + finOut = (finOut * _volumeB) / Audio::Mixer::kMaxMixerVolume; + buffer[i << 1] += finOut; buffer[(i << 1) + 1] += finOut; } @@ -2927,6 +3016,7 @@ TownsPC98_OpnCore::TownsPC98_OpnCore(Audio::Mixer *mixer, OpnType type) : _numChan(type == OD_TYPE26 ? 3 : 6), _numSSG(type == OD_TOWNS ? 0 : 3), _hasPercussion(type == OD_TYPE86 ? true : false), _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0), _baserate(55125.0f / (float)mixer->getOutputRate()), + _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255), _regProtectionFlag(false), _ready(false) { memset(&_timers[0], 0, sizeof(OpnTimer)); @@ -2977,7 +3067,7 @@ bool TownsPC98_OpnCore::init() { _prc->init(_percussionData); } - _mixer->playStream(Audio::Mixer::kMusicSoundType, + _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); _ready = true; @@ -2989,7 +3079,7 @@ void TownsPC98_OpnCore::reset() { for (int i = 0; i < _numChan; i++) { for (int ii = 0; ii < 4; ii++) _chanInternal[i].opr[ii]->reset(); - memset(&_chanInternal[i].feedbuf, 0, 3); + memset(_chanInternal[i].feedbuf, 0, 3); _chanInternal[i].algorithm = 0; _chanInternal[i].frqTemp = 0; _chanInternal[i].enableLeft = _chanInternal[i].enableRight = true; @@ -3228,6 +3318,26 @@ int TownsPC98_OpnCore::readBuffer(int16 *buffer, const int numSamples) { return numSamples; } +void TownsPC98_OpnCore::setVolumeIntern(int volA, int volB) { + Common::StackLock lock(_mutex); + _volumeA = volA; + _volumeB = volB; + if (_ssg) + _ssg->setVolumeIntern(volA, volB); + if (_prc) + _prc->setVolumeIntern(volA, volB); +} + +void TownsPC98_OpnCore::setVolumeChannelMasks(int channelMaskA, int channelMaskB) { + Common::StackLock lock(_mutex); + _volMaskA = channelMaskA; + _volMaskB = channelMaskB; + if (_ssg) + _ssg->setVolumeChannelMasks(_volMaskA >> _numChan, _volMaskB >> _numChan); + if (_prc) + _prc->setVolumeChannelMasks(_volMaskA >> (_numChan + _numSSG), _volMaskB >> (_numChan + _numSSG)); +} + void TownsPC98_OpnCore::generateTables() { delete[] _oprRates; _oprRates = new uint8[128]; @@ -3388,6 +3498,12 @@ void TownsPC98_OpnCore::nextTick(int32 *buffer, uint32 bufferSize) { int32 finOut = (output << 2) / ((_numChan + _numSSG - 3) / 3); + if ((1 << i) & _volMaskA) + finOut = (finOut * _volumeA) / Audio::Mixer::kMaxMixerVolume; + + if ((1 << i) & _volMaskB) + finOut = (finOut * _volumeB) / Audio::Mixer::kMaxMixerVolume; + if (_chanInternal[i].enableLeft) *leftSample += finOut; @@ -3408,11 +3524,14 @@ TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : To _updateChannelsFlag(type == OD_TYPE26 ? 0x07 : 0x3F), _finishedChannelsFlag(0), _updateSSGFlag(type == OD_TOWNS ? 0x00 : 0x07), _finishedSSGFlag(0), _updateRhythmFlag(type == OD_TYPE86 ? 0x01 : 0x00), _finishedRhythmFlag(0), - _updateSfxFlag(type == OD_TOWNS ? 0x00 : 0x06), _finishedSfxFlag(0), + _updateSfxFlag(0), _finishedSfxFlag(0), _musicTickCounter(0), + _musicVolume(255), _sfxVolume(255), + _musicPlaying(false), _sfxPlaying(false), _fading(false), _looping(0), _ready(false) { + _sfxOffsets[0] = _sfxOffsets[1] = 0; } @@ -3450,6 +3569,8 @@ bool TownsPC98_OpnDriver::init() { TownsPC98_OpnCore::init(); + setVolumeChannelMasks(-1, 0); + _channels = new TownsPC98_OpnChannel *[_numChan]; for (int i = 0; i < _numChan; i++) { int ii = i * 6; @@ -3664,8 +3785,11 @@ void TownsPC98_OpnDriver::timerCallbackA() { _trackPtr = _musicBuffer; } - if (_finishedSfxFlag == _updateSfxFlag) + if (_updateSfxFlag && _finishedSfxFlag == _updateSfxFlag) { _sfxPlaying = false; + _updateSfxFlag = 0; + setVolumeChannelMasks(-1, 0); + } } void TownsPC98_OpnDriver::setMusicTempo(uint8 tempo) { @@ -3680,14 +3804,22 @@ void TownsPC98_OpnDriver::setSfxTempo(uint16 tempo) { } void TownsPC98_OpnDriver::startSoundEffect() { + int volFlags = 0; + for (int i = 0; i < 2; i++) { if (_sfxOffsets[i]) { _ssgChannels[i + 1]->protect(); _sfxChannels[i]->reset(); _sfxChannels[i]->loadData(_sfxData + _sfxOffsets[i]); + _updateSfxFlag |= _sfxChannels[i]->_idFlag; + volFlags |= (_sfxChannels[i]->_idFlag << _numChan); + } else { + _ssgChannels[i + 1]->restore(); + _updateSfxFlag &= ~_sfxChannels[i]->_idFlag; } } - + + setVolumeChannelMasks(~volFlags, volFlags); _sfxData = 0; } @@ -4048,7 +4180,9 @@ SoundPC98::~SoundPC98() { bool SoundPC98::init() { _driver = new TownsPC98_OpnDriver(_mixer, TownsPC98_OpnDriver::OD_TYPE26); - return _driver->init(); + bool reslt = _driver->init(); + updateVolumeSettings(); + return reslt; } void SoundPC98::loadSoundFile(uint file) { @@ -4121,6 +4255,13 @@ void SoundPC98::playSoundEffect(uint8 track) { _driver->loadSoundEffectData(_sfxTrackData, track); } +void SoundPC98::updateVolumeSettings() { + if (!_driver) + return; + + _driver->setMusicVolume(ConfMan.getInt("music_volume")); + _driver->setSoundEffectVolume(ConfMan.getInt("sfx_volume")); +} // KYRA 2 @@ -4159,7 +4300,9 @@ bool SoundTownsPC98_v2::init() { _useFmSfx = true; } - return _driver->init(); + bool reslt = _driver->init(); + updateVolumeSettings(); + return reslt; } void SoundTownsPC98_v2::loadSoundFile(Common::String file) { @@ -4314,6 +4457,14 @@ void SoundTownsPC98_v2::playSoundEffect(uint8 track) { _driver->loadSoundEffectData(_sfxTrackData, track); } +void SoundTownsPC98_v2::updateVolumeSettings() { + if (!_driver) + return; + + _driver->setMusicVolume(ConfMan.getInt("music_volume")); + _driver->setSoundEffectVolume(ConfMan.getInt("sfx_volume")); +} + // static resources const uint32 TownsPC98_OpnCore::_adtStat[] = { diff --git a/engines/lure/detection.cpp b/engines/lure/detection.cpp index 36c1cf237d..dd2a702e2a 100644 --- a/engines/lure/detection.cpp +++ b/engines/lure/detection.cpp @@ -196,7 +196,11 @@ static const ADParams detectionParams = { // Flags kADFlagUseExtraAsHint, // Additional GUI options (for every game} - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH, + // Maximum directory depth + 1, + // List of directory globs + 0 }; class LureMetaEngine : public AdvancedMetaEngine { diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp index e725b7c31a..cd539dfab4 100644 --- a/engines/lure/sound.cpp +++ b/engines/lure/sound.cpp @@ -50,13 +50,13 @@ SoundManager::SoundManager() { _soundData = NULL; _paused = false; - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - _isRoland = midiDriver != MD_ADLIB; - _nativeMT32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MT32); + _isRoland = MidiDriver::getMusicType(dev) != MT_ADLIB; + _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); Common::set_to(_channelsInUse, _channelsInUse + NUM_CHANNELS, false); - _driver = MidiDriver::createMidi(midiDriver); + _driver = MidiDriver::createMidi(dev); int statusCode = _driver->open(); if (statusCode) { warning("Sound driver returned error code %d", statusCode); diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp index 1142ba48d1..0ead57aac9 100644 --- a/engines/m4/animation.cpp +++ b/engines/m4/animation.cpp @@ -44,6 +44,7 @@ MadsAnimation::MadsAnimation(MadsM4Engine *vm, MadsView *view): Animation(vm), _ _currentFrame = 0; _oldFrameEntry = 0; _nextFrameTimer = _madsVm->_currentTimer; + _nextScrollTimer = 0; } MadsAnimation::~MadsAnimation() { @@ -56,14 +57,14 @@ MadsAnimation::~MadsAnimation() { if (_field12) { _view->_spriteSlots.deleteSprites(_spriteListIndexes[_spriteListIndex]); } - - delete _font; } +#define FILENAME_SIZE 13 + /** * Initialises and loads the data of an animation */ -void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4Surface *interfaceSurface, M4Surface *sceneSurface) { +void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4Surface *surface, M4Surface *depthSurface) { MadsPack anim(filename.c_str(), _vm); bool madsRes = filename[0] == '*'; char buffer[20]; @@ -87,34 +88,49 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S animStream->skip(2); _field12 = animStream->readUint16LE() != 0; _spriteListIndex = animStream->readUint16LE(); - _scrollX = animStream->readUint16LE(); + _scrollX = animStream->readSint16LE(); _scrollY = animStream->readSint16LE(); - animStream->skip(10); + _scrollTicks = animStream->readUint16LE(); + animStream->skip(8); - animStream->read(buffer, 13); - _interfaceFile = Common::String(buffer, 13); + animStream->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + _interfaceFile = Common::String(buffer); for (int i = 0; i < 10; ++i) { - animStream->read(buffer, 13); - _spriteSetNames[i] = Common::String(buffer, 13); + animStream->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + _spriteSetNames[i] = Common::String(buffer); } animStream->skip(81); - animStream->read(buffer, 13); - _lbmFilename = Common::String(buffer, 13); - animStream->read(buffer, 13); - _spritesFilename = Common::String(buffer, 13); + animStream->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + _lbmFilename = Common::String(buffer); + + animStream->skip(365); + animStream->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + _spritesFilename = Common::String(buffer); + animStream->skip(48); - animStream->read(buffer, 13); - _soundName = Common::String(buffer, 13); - animStream->skip(26); - animStream->read(buffer, 13); - Common::String fontResource(buffer, 13); + animStream->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + _soundName = Common::String(buffer); + + animStream->skip(13); + animStream->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + _dsrName = Common::String(buffer); + + animStream->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + Common::String fontResource(buffer); if (_animMode == 4) flags |= 0x4000; if (flags & 0x100) - loadInterface(interfaceSurface, sceneSurface); + loadInterface(surface, depthSurface); // Initialise the reference list for (int i = 0; i < spriteListCount; ++i) @@ -130,21 +146,24 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S 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(); + rec.soundId = animStream->readSint16LE(); + animStream->read(rec.msg, 64); + animStream->skip(4); + rec.pos.x = animStream->readSint16LE(); + rec.pos.y = animStream->readSint16LE(); + rec.flags = animStream->readUint16LE(); + rec.rgb1.r = animStream->readByte() << 2; + rec.rgb1.g = animStream->readByte() << 2; + rec.rgb1.b = animStream->readByte() << 2; + rec.rgb2.r = animStream->readByte() << 2; + rec.rgb2.g = animStream->readByte() << 2; + rec.rgb2.b = animStream->readByte() << 2; + animStream->skip(2); // Space for kernelMsgIndex + rec.kernelMsgIndex = -1; animStream->skip(6); rec.startFrame = animStream->readUint16LE(); rec.endFrame = animStream->readUint16LE(); - animStream->readUint16LE(); + animStream->skip(2); _messages.push_back(rec); } @@ -162,9 +181,9 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S 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.xp = animStream->readSint16LE(); + rec.spriteSlot.yp = animStream->readSint16LE(); + rec.spriteSlot.depth = animStream->readSByte(); rec.spriteSlot.scale = (int8)animStream->readByte(); _frameEntries.push_back(rec); @@ -180,7 +199,7 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S for (int i = 0; i < miscEntriesCount; ++i) { AnimMiscEntry rec; rec.soundNum = animStream->readByte(); - animStream->skip(1); + rec.msgIndex = animStream->readSByte(); rec.numTicks = animStream->readUint16LE(); rec.posAdjust.x = animStream->readUint16LE(); rec.posAdjust.y = animStream->readUint16LE(); @@ -199,9 +218,16 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S fontName += "*"; fontName += fontResource; - _font = _vm->_font->getFont(fontName); + if (fontName != "") + _font = _vm->_font->getFont(fontName.c_str()); + else + warning("Attempted to set a font with an empty name"); } + // If a speech file is specified, then load it + if (!_dsrName.empty()) + _vm->_sound->loadDSRFile(_dsrName.c_str()); + // Load all the sprite sets for the animation for (int i = 0; i < spriteListCount; ++i) { if (_field12 && (i == _spriteListIndex)) @@ -232,6 +258,9 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S int idx = _frameEntries[i].spriteSlot.spriteListIndex; _frameEntries[i].spriteSlot.spriteListIndex = _spriteListIndexes[idx]; } + + if (hasScroll()) + _nextScrollTimer = _madsVm->_currentTimer + _scrollTicks; } /** @@ -259,7 +288,7 @@ void MadsAnimation::load(const Common::String &filename, int abortTimers) { _abortMode = _madsVm->scene()->_abortTimersMode2; for (int i = 0; i < 3; ++i) - _actionNouns[i] = _madsVm->scene()->actionNouns[i]; + _actionNouns[i] = _madsVm->globals()->actionNouns[i]; // Initialise kernel message list for (uint i = 0; i < _messages.size(); ++i) @@ -282,9 +311,24 @@ void MadsAnimation::update() { load1(newIndex); } + // Check for scroll change + bool screenChanged = false; + + // Handle any scrolling of the screen surface + if (hasScroll() && (_madsVm->_currentTimer >= _nextScrollTimer)) { + _view->_bgSurface->scrollX(_scrollX); + _view->_bgSurface->scrollY(_scrollY); + + _nextScrollTimer = _madsVm->_currentTimer + _scrollTicks; + screenChanged = true; + } + // If it's not time for the next frame, then exit - if (_madsVm->_currentTimer < _nextFrameTimer) + if (_madsVm->_currentTimer < _nextFrameTimer) { + if (screenChanged) + _view->_spriteSlots.fullRefresh(); return; + } // Loop checks for any prior animation sprite slots to be expired for (int slotIndex = 0; slotIndex < _view->_spriteSlots.startIndex; ++slotIndex) { @@ -311,25 +355,17 @@ void MadsAnimation::update() { if (misc.soundNum) _vm->_sound->playSound(misc.soundNum); - bool screenChanged = false; - - // 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; + _view->_posAdjust.x = misc.posAdjust.x; screenChanged = true; } if (_view->_posAdjust.y != misc.posAdjust.y) { - misc.posAdjust.y = _view->_posAdjust.y; + _view->_posAdjust.y = misc.posAdjust.y; screenChanged = true; } + + if (screenChanged) { // Signal the entire screen needs refreshing _view->_spriteSlots.fullRefresh(); @@ -408,7 +444,12 @@ void MadsAnimation::update() { _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); + me.kernelMsgIndex = _view->_kernelMessages.add(me.pos, colIndex * 0x101 + 0x100, 0, 0, INDEFINITE_TIMEOUT, me.msg); + assert(me.kernelMsgIndex >= 0); + + // Play the associated sound, if it exists + if (me.soundId > 0) + _vm->_sound->playDSRSound(me.soundId - 1, 255, false); ++_messageCtr; } } @@ -424,7 +465,7 @@ void MadsAnimation::update() { if (_abortMode != ABORTMODE_1) { // Copy the noun list for (int i = 0; i < 3; ++i) - _madsVm->scene()->actionNouns[i] = _actionNouns[i]; + _madsVm->globals()->actionNouns[i] = _actionNouns[i]; } } } @@ -437,6 +478,12 @@ void MadsAnimation::setCurrentFrame(int frameNumber) { _currentFrame = frameNumber; _oldFrameEntry = 0; _freeFlag = false; + + _nextScrollTimer = _nextFrameTimer = _madsVm->_currentTimer; +} + +int MadsAnimation::getCurrentFrame() { + return _currentFrame; } void MadsAnimation::load1(int frameNumber) { diff --git a/engines/m4/animation.h b/engines/m4/animation.h index 5c7227a256..583d829066 100644 --- a/engines/m4/animation.h +++ b/engines/m4/animation.h @@ -39,12 +39,13 @@ class SpriteSlotSubset; class AnimMessage { public: - char msg[70]; + int16 soundId; + char msg[64]; Common::Point pos; RGB8 rgb1, rgb2; - int kernelMsgIndex; - + uint16 flags; int startFrame, endFrame; + int kernelMsgIndex; }; class AnimFrameEntry { @@ -57,6 +58,7 @@ public: class AnimMiscEntry { public: int soundNum; + int msgIndex; int numTicks; Common::Point posAdjust; }; @@ -82,11 +84,13 @@ private: int _spriteListIndex; int _scrollX; int _scrollY; + int _scrollTicks; Common::String _interfaceFile; Common::String _spriteSetNames[10]; Common::String _lbmFilename; Common::String _spritesFilename; Common::String _soundName; + Common::String _dsrName; Common::Array<int> _spriteListIndexes; int _currentFrame, _oldFrameEntry; @@ -96,24 +100,29 @@ private: int _unkIndex; Common::Point _unkList[2]; uint32 _nextFrameTimer; + uint32 _nextScrollTimer; 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); + bool hasScroll() const { return (_scrollX != 0) || (_scrollY != 0); } public: MadsAnimation(MadsM4Engine *vm, MadsView *view); virtual ~MadsAnimation(); - virtual void initialise(const Common::String &filename, uint16 flags, M4Surface *interfaceSurface, M4Surface *sceneSurface); + virtual void initialise(const Common::String &filename, uint16 flags, M4Surface *surface, M4Surface *depthSurface); virtual void load(const Common::String &filename, int abortTimers); virtual void update(); virtual void setCurrentFrame(int frameNumber); + virtual int getCurrentFrame(); bool freeFlag() const { return _freeFlag; } + bool getAnimMode() const { return _animMode; } int roomNumber() const { return _roomNumber; } }; diff --git a/engines/m4/assets.cpp b/engines/m4/assets.cpp index 1f3cf278ae..23122eb960 100644 --- a/engines/m4/assets.cpp +++ b/engines/m4/assets.cpp @@ -98,7 +98,8 @@ long *DataAsset::getRow(int index) { return &_data[_recSize * index]; } -SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream) : +SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, + bool asStream, int flags) : BaseAsset(vm) { _stream = stream; _palInterface = NULL; @@ -107,7 +108,7 @@ SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, i if (_vm->isM4()) { loadM4SpriteAsset(vm, stream, asStream); } else { - loadMadsSpriteAsset(vm, stream); + loadMadsSpriteAsset(vm, stream, flags); } } @@ -119,7 +120,7 @@ SpriteAsset::SpriteAsset(MadsM4Engine *vm, const char *name): BaseAsset(vm) { if (_vm->isM4()) { loadM4SpriteAsset(vm, _stream, true); } else { - loadMadsSpriteAsset(vm, _stream); + loadMadsSpriteAsset(vm, _stream, 0); } vm->res()->toss(name); @@ -136,6 +137,8 @@ SpriteAsset::~SpriteAsset() { for (Common::Array<SpriteAssetFrame>::iterator it = _frames.begin(); it != _frames.end(); ++it) { delete (*it).frame; } + + delete _charInfo; } void SpriteAsset::loadM4SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, bool asStream) { @@ -200,7 +203,7 @@ void SpriteAsset::loadM4SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream } -void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream) { +void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int flags) { int curFrame = 0; uint32 frameOffset = 0; MadsPack sprite(stream); @@ -217,7 +220,12 @@ void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStre _isBackground = (type1 != 0) && (type2 < 4); spriteStream->skip(32); _frameCount = spriteStream->readUint16LE(); - // we skip the rest of the data + + if (_vm->isM4() || ((flags & SPRITE_SET_CHAR_INFO) == 0)) + _charInfo = NULL; + else + _charInfo = new MadsSpriteSetCharInfo(spriteStream); + delete spriteStream; // Get the palette data @@ -234,12 +242,15 @@ void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStre spriteStream = sprite.getItemStream(1); Common::SeekableReadStream *spriteDataStream = sprite.getItemStream(3); SpriteAssetFrame frame; + Common::Array<int> frameSizes; for (curFrame = 0; curFrame < _frameCount; curFrame++) { frame.stream = 0; frame.comp = 0; frameOffset = spriteStream->readUint32LE(); _frameOffsets.push_back(frameOffset); - spriteStream->readUint32LE(); // frame size + uint32 frameSize = spriteStream->readUint32LE(); + frameSizes.push_back(frameSize); + frame.x = spriteStream->readUint16LE(); frame.y = spriteStream->readUint16LE(); frame.w = spriteStream->readUint16LE(); @@ -247,9 +258,44 @@ void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStre if (curFrame == 0) debugC(1, kDebugGraphics, "%i frames, x = %i, y = %i, w = %i, h = %i\n", _frameCount, frame.x, frame.y, frame.w, frame.h); - frame.frame = new M4Sprite(spriteDataStream, frame.x, frame.y, frame.w, frame.h, false); + if (_mode == 0) { + // Create a frame and decompress the raw pixel data + uint32 currPos = (uint32)spriteDataStream->pos(); + frame.frame = new M4Sprite(spriteDataStream, frame.x, frame.y, frame.w, frame.h, false); + assert((uint32)spriteDataStream->pos() == (currPos + frameSize)); + } + _frames.push_back(frame); } + + if (_mode != 0) { + // Handle decompressing Fab encoded data + for (curFrame = 0; curFrame < _frameCount; curFrame++) { + FabDecompressor fab; + + int srcSize = (curFrame == (_frameCount - 1)) ? spriteDataStream->size() - _frameOffsets[curFrame] : + _frameOffsets[curFrame + 1] - _frameOffsets[curFrame]; + byte *srcData = (byte *)malloc(srcSize); + assert(srcData); + spriteDataStream->read(srcData, srcSize); + + byte *destData = (byte *)malloc(frameSizes[curFrame]); + assert(destData); + + fab.decompress(srcData, srcSize, destData, frameSizes[curFrame]); + + // Load the frame + Common::MemoryReadStream *rs = new Common::MemoryReadStream(destData, frameSizes[curFrame]); + _frames[curFrame].frame = new M4Sprite(rs, _frames[curFrame].x, _frames[curFrame].y, + _frames[curFrame].w, _frames[curFrame].h, false); + delete rs; + + free(srcData); + free(destData); + } + } + + delete spriteStream; delete spriteDataStream; } @@ -320,7 +366,12 @@ void SpriteAsset::loadFrameHeader(SpriteAssetFrame &frameHeader, bool isBigEndia } M4Sprite *SpriteAsset::getFrame(int frameIndex) { - return _frames[frameIndex].frame; + if ((uint)frameIndex < _frames.size()) { + return _frames[frameIndex].frame; + } else { + warning("SpriteAsset::getFrame: Invalid frame %d, out of %d", frameIndex, _frames.size()); + return _frames[_frames.size() - 1].frame; + } } void SpriteAsset::loadStreamingFrame(M4Sprite *frame, int frameIndex, int destX, int destY) { @@ -578,4 +629,23 @@ int32 AssetManager::getSpriteFrameCount(int32 hash) { return _CELS[hash]->getCount(); } +//-------------------------------------------------------------------------- + +MadsSpriteSetCharInfo::MadsSpriteSetCharInfo(Common::SeekableReadStream *s) { + _totalFrames = s->readByte(); + s->skip(1); + _numEntries = s->readUint16LE(); + + for (int i = 0; i < 16; ++i) + _frameList[i] = s->readUint16LE(); + for (int i = 0; i < 16; ++i) + _frameList2[i] = s->readUint16LE(); + for (int i = 0; i < 16; ++i) + _ticksList[i] = s->readUint16LE(); + + _unk1 = s->readUint16LE(); + _ticksAmount = s->readByte(); + _yScale = s->readByte(); +} + } // End of namespace M4 diff --git a/engines/m4/assets.h b/engines/m4/assets.h index e5beffbcae..3ae7fb2e22 100644 --- a/engines/m4/assets.h +++ b/engines/m4/assets.h @@ -44,6 +44,8 @@ namespace M4 { #define CELS__PAL MKID_BE(' PAL') //' PAL' #define CELS___SS MKID_BE(' SS') //' SS' +#define SPRITE_SET_CHAR_INFO 4 + class MadsM4Engine; class Palette; @@ -100,13 +102,28 @@ struct SpriteAssetFrame { M4Sprite *frame; }; +class MadsSpriteSetCharInfo { +public: + MadsSpriteSetCharInfo(Common::SeekableReadStream *s); + + int _totalFrames; + int _numEntries; + int _frameList2[16]; + int _frameList[16]; + int _ticksList[16]; + int _unk1; + int _ticksAmount; + int _yScale; +}; + class SpriteAsset : public BaseAsset { 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, int flags = 0); SpriteAsset(MadsM4Engine *vm, const char *name); ~SpriteAsset(); void loadM4SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, bool asStream); - void loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream); + void loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int flags); int32 getCount() { return _frameCount; } int32 getFrameRate() const { return _frameRate; } int32 getPixelSpeed() const { return _pixelSpeed; } @@ -124,6 +141,8 @@ public: void translate(Palette *palette); int32 getFrameSize(int index); M4Sprite *operator[](int index) { return getFrame(index); } +public: + MadsSpriteSetCharInfo *_charInfo; protected: Common::SeekableReadStream *_stream; RGB8 _palette[256]; diff --git a/engines/m4/console.cpp b/engines/m4/console.cpp index 4e14afdfaf..19fbf6e852 100644 --- a/engines/m4/console.cpp +++ b/engines/m4/console.cpp @@ -196,7 +196,7 @@ bool Console::cmdShowSprite(int argc, const char **argv) { if (y >= bg->height()) break; - spr->copyTo(bg, x, y, (int)spr->getTransparentColor()); + spr->copyTo(bg, x, y, (int)spr->getTransparencyIndex()); x += spr->width(); yMax = MAX(yMax, spr->height()); diff --git a/engines/m4/detection.cpp b/engines/m4/detection.cpp index 9493226c1a..4b204996f3 100644 --- a/engines/m4/detection.cpp +++ b/engines/m4/detection.cpp @@ -400,7 +400,11 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NOMIDI + Common::GUIO_NOMIDI, + // Maximum directory depth + 1, + // List of directory globs + 0 }; class M4MetaEngine : public AdvancedMetaEngine { diff --git a/engines/m4/events.cpp b/engines/m4/events.cpp index c0ca412f11..c66609844a 100644 --- a/engines/m4/events.cpp +++ b/engines/m4/events.cpp @@ -57,6 +57,10 @@ Events::Events(MadsM4Engine *vm) : _vm(vm) { _console = new MadsConsole(_madsVm); } +Events::~Events() { + delete _console; +} + M4EventType Events::handleEvents() { static int oldX = -1, oldY = -1; static uint32 dclickTime = 0; @@ -252,7 +256,8 @@ bool Mouse::setCursorNum(int cursorIndex) { _cursor = _cursorSprites->getFrame(cursorIndex); // Set the cursor to the sprite - CursorMan.replaceCursor((const byte *)_cursor->getBasePtr(), _cursor->width(), _cursor->height(), _cursor->xOffset, _cursor->yOffset, 0); + CursorMan.replaceCursor((const byte *)_cursor->getBasePtr(), _cursor->width(), _cursor->height(), + _cursor->xOffset, _cursor->yOffset, TRANSPARENT_COLOUR_INDEX); return true; } diff --git a/engines/m4/events.h b/engines/m4/events.h index 43b61c8f0d..1c1418d5f8 100644 --- a/engines/m4/events.h +++ b/engines/m4/events.h @@ -78,6 +78,7 @@ private: public: bool quitFlag; Events(MadsM4Engine *vm); + virtual ~Events(); Common::Event &event() { return _event; } Common::EventType type() { return _event.type; } diff --git a/engines/m4/font.cpp b/engines/m4/font.cpp index 4afa158976..b5965732e5 100644 --- a/engines/m4/font.cpp +++ b/engines/m4/font.cpp @@ -35,27 +35,34 @@ FontManager::~FontManager() { _entries.clear(); } -Font *FontManager::getFont(const Common::String &filename) { +Font *FontManager::getFont(const char *filename) { + // Append an extension if the filename doesn't already have one + char buffer[20]; + strncpy(buffer, filename, 19); + if (!strchr(buffer, '.')) + strcat(buffer, ".ff"); + // Check if the font is already loaded - for (uint i = 0; i < _entries.size(); ++i) - { - if (_entries[i]->_filename.equals(filename)) + for (uint i = 0; i < _entries.size(); ++i) { + if (!strcmp(_entries[i]->_filename, buffer)) return _entries[i]; } - Font *f = new Font(_vm, filename); + Font *f = new Font(_vm, buffer); _entries.push_back(f); return f; } -void FontManager::setFont(const Common::String &filename) { +void FontManager::setFont(const char *filename) { _currentFont = getFont(filename); } //-------------------------------------------------------------------------- -Font::Font(MadsM4Engine *vm, const Common::String &filename) : _vm(vm), _filename(filename) { +Font::Font(MadsM4Engine *vm, const char *filename) : _vm(vm) { _sysFont = true; + strncpy(_filename, filename, 19); + _filename[19] = '\0'; //TODO: System font _fontColors[0] = _vm->_palette->BLACK; @@ -66,9 +73,9 @@ Font::Font(MadsM4Engine *vm, const Common::String &filename) : _vm(vm), _filenam _sysFont = false; if (_vm->isM4()) - setFontM4(filename.c_str()); + setFontM4(filename); else - setFontMads(filename.c_str()); + setFontMads(filename); } void Font::setFontM4(const char *filename) { diff --git a/engines/m4/font.h b/engines/m4/font.h index ca47848c61..19d15faa1e 100644 --- a/engines/m4/font.h +++ b/engines/m4/font.h @@ -59,7 +59,7 @@ namespace M4 { class Font { public: - Font(MadsM4Engine *vm, const Common::String &filename); + Font(MadsM4Engine *vm, const char *filename); ~Font(); void setColour(uint8 colour); @@ -73,7 +73,7 @@ public: return write(surface, text, x, y, width, spaceWidth, _fontColors); } public: - const Common::String _filename; + char _filename[20]; private: void setFontM4(const char *filename); void setFontMads(const char *filename); @@ -108,8 +108,8 @@ public: FontManager(MadsM4Engine *vm): _vm(vm) { _currentFont = NULL; } ~FontManager(); - Font *getFont(const Common::String &filename); - void setFont(const Common::String &filename); + Font *getFont(const char *filename); + void setFont(const char *filename); Font *current() { assert(_currentFont); diff --git a/engines/m4/globals.cpp b/engines/m4/globals.cpp index 1768c71787..a96229a0b3 100644 --- a/engines/m4/globals.cpp +++ b/engines/m4/globals.cpp @@ -282,6 +282,9 @@ MadsGlobals::MadsGlobals(MadsEngine *vm): Globals(vm) { playerSpriteChanged = false; dialogType = DIALOG_NONE; sceneNumber = -1; + for (int i = 0; i < 3; ++i) + actionNouns[i] = 0; + _difficultyLevel = 0; } MadsGlobals::~MadsGlobals() { @@ -351,16 +354,16 @@ void MadsGlobals::loadMadsMessagesInfo() { //printf("%i messages\n", count); for (int i = 0; i < count; i++) { - MessageItem *curMessage = new MessageItem(); - curMessage->id = messageS->readUint32LE(); - curMessage->offset = messageS->readUint32LE(); - curMessage->uncompSize = messageS->readUint16LE(); + MessageItem curMessage; + curMessage.id = messageS->readUint32LE(); + curMessage.offset = messageS->readUint32LE(); + curMessage.uncompSize = messageS->readUint16LE(); if (i > 0) - _madsMessages[i - 1]->compSize = curMessage->offset - _madsMessages[i - 1]->offset; + _madsMessages[i - 1].compSize = curMessage.offset - _madsMessages[i - 1].offset; if (i == count - 1) - curMessage->compSize = messageS->size() - curMessage->offset; + curMessage.compSize = messageS->size() - curMessage.offset; //printf("id: %i, offset: %i, uncomp size: %i\n", curMessage->id, curMessage->offset, curMessage->uncompSize); _madsMessages.push_back(curMessage); @@ -382,7 +385,7 @@ void MadsGlobals::loadMadsObjects() { int MadsGlobals::messageIndexOf(uint32 messageId) { for (uint i = 0; i < _madsMessages.size(); ++i) { - if (_madsMessages[i]->id == messageId) + if (_madsMessages[i].id == messageId) return i; } return -1; @@ -395,15 +398,15 @@ const char *MadsGlobals::loadMessage(uint index) { } FabDecompressor fab; - byte *compData = new byte[_madsMessages[index]->compSize]; - byte *buffer = new byte[_madsMessages[index]->uncompSize]; + byte *compData = new byte[_madsMessages[index].compSize]; + byte *buffer = new byte[_madsMessages[index].uncompSize]; Common::SeekableReadStream *messageS = _vm->res()->get("messages.dat"); - messageS->seek(_madsMessages[index]->offset, SEEK_SET); - messageS->read(compData, _madsMessages[index]->compSize); - fab.decompress(compData, _madsMessages[index]->compSize, buffer, _madsMessages[index]->uncompSize); + messageS->seek(_madsMessages[index].offset, SEEK_SET); + messageS->read(compData, _madsMessages[index].compSize); + fab.decompress(compData, _madsMessages[index].compSize, buffer, _madsMessages[index].uncompSize); - for (int i = 0; i < _madsMessages[index]->uncompSize - 1; i++) + for (int i = 0; i < _madsMessages[index].uncompSize - 1; i++) if (buffer[i] == '\0') buffer[i] = '\n'; _vm->res()->toss("messages.dat"); @@ -526,7 +529,9 @@ void MadsObject::load(Common::SeekableReadStream *stream) { roomNumber = READ_LE_UINT16(&obj[2]); article = (MADSArticles)obj[4]; vocabCount = obj[5] & 0x7f; - assert(vocabCount <= 3); + // Phantom / Dragon + if (vocabCount > 3) + warning("MadsObject::load(), vocab cound > 3 (it's %d)", vocabCount); for (int i = 0; i < vocabCount; ++i) { vocabList[i].flags1 = obj[6 + i * 4]; diff --git a/engines/m4/globals.h b/engines/m4/globals.h index de6e716ece..3fc31b4ec2 100644 --- a/engines/m4/globals.h +++ b/engines/m4/globals.h @@ -28,6 +28,7 @@ #include "common/scummsys.h" #include "common/array.h" +#include "common/hashmap.h" #include "common/rect.h" #include "common/file.h" #include "common/list.h" @@ -149,7 +150,7 @@ public: void pauseGame(bool value); }; -#define TOTAL_NUM_VARIABLES 256 +#define TOTAL_NUM_VARIABLES 210 #define PLAYER_INVENTORY 2 @@ -223,6 +224,13 @@ struct MadsConfigData { int screenFades; }; +#define GET_GLOBAL(x) (_madsVm->globals()->_globals[x]) +#define GET_GLOBAL32(x) (((uint32)_madsVm->globals()->_globals[x + 1] << 16) | _madsVm->globals()->_globals[x]) +#define SET_GLOBAL(x,y) _madsVm->globals()->_globals[x] = y +#define SET_GLOBAL32(x,y) { _madsVm->globals()->_globals[x] = (y) & 0xffff; _madsVm->globals()->_globals[(x) + 1] = (y) >> 16; } + +typedef Common::HashMap<uint16, uint16> IntStorage; + class MadsGlobals : public Globals { private: struct MessageItem { @@ -235,7 +243,7 @@ private: MadsEngine *_vm; Common::Array<char* > _madsVocab; Common::Array<char* > _madsQuotes; - Common::Array<MessageItem* > _madsMessages; + Common::Array<MessageItem> _madsMessages; MadsObjectArray _madsObjects; Common::List<int> _visitedScenes; public: @@ -243,12 +251,16 @@ public: ~MadsGlobals(); // MADS variables - int _globals[TOTAL_NUM_VARIABLES]; + uint16 _globals[TOTAL_NUM_VARIABLES]; MadsConfigData _config; bool playerSpriteChanged; MadsDialogType dialogType; int sceneNumber; int previousScene; + int16 _nextSceneId; + uint16 actionNouns[3]; + IntStorage _dataMap; + int _difficultyLevel; void loadMadsVocab(); uint32 getVocabSize() { return _madsVocab.size(); } diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp index 8624f18da1..c10ea6c9f6 100644 --- a/engines/m4/graphics.cpp +++ b/engines/m4/graphics.cpp @@ -65,6 +65,15 @@ void RGBList::setRange(int start, int count, const RGB8 *src) { Common::copy(&src[0], &src[count], &_data[start]); } +/** + * Creates a duplicate of the given rgb list + */ +RGBList *RGBList::clone() const { + RGBList *dest = new RGBList(_size, _data, false); + _madsVm->_palette->addRange(dest); + return dest; +} + //-------------------------------------------------------------------------- #define VGA_COLOR_TRANS(x) (x == 0x3f ? 255 : x << 2) @@ -74,6 +83,8 @@ M4Surface::~M4Surface() { _madsVm->_palette->deleteRange(_rgbList); delete _rgbList; } + if (_ownsData) + free(); } void M4Surface::loadCodesM4(Common::SeekableReadStream *source) { @@ -331,6 +342,16 @@ void M4Surface::clear() { Common::set_to((byte *)pixels, (byte *)pixels + w * h, _vm->_palette->BLACK); } +void M4Surface::reset() { + ::free(pixels); + pixels = NULL; + if (_rgbList) { + _vm->_palette->deleteRange(_rgbList); + delete _rgbList; + _rgbList = NULL; + } +} + void M4Surface::frameRect(const Common::Rect &r, uint8 color) { Graphics::Surface::frameRect(r, color); } @@ -389,38 +410,35 @@ void M4Surface::copyFrom(M4Surface *src, const Common::Rect &srcBounds, int dest * Copies a given image onto a destination surface with scaling, transferring only pixels that meet * the specified depth requirement on a secondary surface contain depth information */ -void M4Surface::copyFrom(M4Surface *src, int destX, int destY, int depth, M4Surface *depthsSurface, - int scale, int transparentColour) { - /* TODO: This isn't a straight re-implementation of the original draw routine. Double check in future - * whether this implementation provides equivalent functionality - */ - Common::Rect copyRect(0, 0, src->width(), src->height()); +void M4Surface::copyFrom(M4Surface *src, int destX, int destY, int depth, + M4Surface *depthsSurface, int scale, int transparentColour) { - if (destX < 0) { - copyRect.left += -destX; - destX = 0; - } else if (destX + copyRect.width() > w) { - copyRect.right -= destX + copyRect.width() - w; - } - if (destY < 0) { - copyRect.top += -destY; - destY = 0; - } else if (destY + copyRect.height() > h) { - copyRect.bottom -= destY + copyRect.height() - h; - } - - if (!copyRect.isValidRect()) - return; + if (scale == 100) { + // Copy the specified area + Common::Rect copyRect(0, 0, src->width(), src->height()); + + if (destX < 0) { + copyRect.left += -destX; + destX = 0; + } else if (destX + copyRect.width() > w) { + copyRect.right -= destX + copyRect.width() - w; + } + if (destY < 0) { + copyRect.top += -destY; + destY = 0; + } else if (destY + copyRect.height() > h) { + copyRect.bottom -= destY + copyRect.height() - h; + } - // Copy the specified area + if (!copyRect.isValidRect()) + return; - byte *data = src->getBasePtr(); - byte *srcPtr = data + (src->width() * copyRect.top + copyRect.left); - byte *depthsData = depthsSurface->getBasePtr(); - byte *depthsPtr = depthsData + (src->width() * copyRect.top + copyRect.left); - byte *destPtr = (byte *)pixels + (destY * width()) + destX; + byte *data = src->getBasePtr(); + byte *srcPtr = data + (src->width() * copyRect.top + copyRect.left); + byte *depthsData = depthsSurface->getBasePtr(); + byte *depthsPtr = depthsData + (depthsSurface->pitch * destY) + destX; + byte *destPtr = (byte *)pixels + (destY * pitch) + destX; - if (scale == 100) { // 100% scaling variation for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) { // Copy each byte one at a time checking against the depth @@ -433,31 +451,127 @@ void M4Surface::copyFrom(M4Surface *src, int destX, int destY, int depth, M4Surf depthsPtr += depthsSurface->width(); destPtr += width(); } - } else { - // Scaled variation - for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) { - int currX = -1; - // Loop through the source pixels - for (int xCtr = 0, xTotal = 0; xCtr < copyRect.width(); ++xCtr, xTotal += (100 - scale)) { - int srcX = xTotal / 100; + src->freeData(); + depthsSurface->freeData(); + return; + } - if (srcX != currX) { - currX = srcX; + // Start of draw logic for scaled sprites + const byte *srcPixelsP = src->getBasePtr(); + + int destRight = this->width() - 1; + int destBottom = this->height() - 1; + bool normalFrame = true; // TODO: false for negative frame numbers + int frameWidth = src->width(); + int frameHeight = src->height(); + + int highestDim = MAX(frameWidth, frameHeight); + bool lineDist[MADS_SURFACE_WIDTH]; + int distIndex = 0; + int distXCount = 0, distYCount = 0; + + int distCtr = 0; + do { + distCtr += scale; + if (distCtr < 100) { + lineDist[distIndex] = false; + } else { + lineDist[distIndex] = true; + distCtr -= 100; - if ((depthsPtr[currX] > depth) && (srcPtr[xCtr] != transparentColour)) - destPtr[currX] = srcPtr[xCtr]; - } - } + if (distIndex < frameWidth) + ++distXCount; - srcPtr += src->width(); - depthsPtr += depthsSurface->width(); - destPtr += width(); + if (distIndex < frameHeight) + ++distYCount; } + } while (++distIndex < highestDim); + + destX -= distXCount / 2; + destY -= distYCount - 1; + + // Check x bounding area + int spriteLeft = 0; + int spriteWidth = distXCount; + int widthAmount = destX + distXCount - 1; + + if (destX < 0) { + spriteWidth += destX; + spriteLeft -= destX; + } + widthAmount -= destRight; + if (widthAmount > 0) + spriteWidth -= widthAmount; + + int spriteRight = spriteLeft + spriteWidth; + if (spriteWidth <= 0) + return; + if (!normalFrame) { + destX += distXCount - 1; + spriteLeft = -(distXCount - spriteRight); + spriteRight = (-spriteLeft + spriteWidth); + } + + // Check y bounding area + int spriteTop = 0; + int spriteHeight = distYCount; + int heightAmount = destY + distYCount - 1; + + if (destY < 0) { + spriteHeight += destY; + spriteTop -= destY; + } + heightAmount -= destBottom; + if (heightAmount > 0) + spriteHeight -= heightAmount; + int spriteBottom = spriteTop + spriteHeight; + + if (spriteHeight <= 0) + return; + + byte *destPixelsP = this->getBasePtr(destX + spriteLeft, destY + spriteTop); + const byte *depthPixelsP = depthsSurface->getBasePtr(destX + spriteLeft, destY + spriteTop); + + spriteLeft = (spriteLeft * (normalFrame ? 1 : -1)); + + // Loop through the lines of the sprite + for (int yp = 0, sprY = -1; yp < frameHeight; ++yp, srcPixelsP += src->pitch) { + if (!lineDist[yp]) + // Not a display line, so skip it + continue; + // Check whether the sprite line is in the display range + ++sprY; + if ((sprY >= spriteBottom) || (sprY < spriteTop)) + continue; + + // Found a line to display. Loop through the pixels + const byte *srcP = srcPixelsP; + const byte *depthP = depthPixelsP; + byte *destP = destPixelsP; + for (int xp = 0, sprX = 0; xp < frameWidth; ++xp, ++srcP) { + if (xp < spriteLeft) + // Not yet reached start of display area + continue; + if (!lineDist[sprX++]) + // Not a display pixel + continue; + + if ((*srcP != transparentColour) && (depth <= *depthP)) + *destP = *srcP; + + ++destP; + ++depthP; + } + + // Move to the next destination line + destPixelsP += this->pitch; + depthPixelsP += depthsSurface->pitch; } src->freeData(); depthsSurface->freeData(); + this->freeData(); } void M4Surface::loadBackgroundRiddle(const char *sceneName) { @@ -471,8 +585,6 @@ void M4Surface::loadBackgroundRiddle(const char *sceneName) { } void M4Surface::loadBackground(int sceneNumber, RGBList **palData) { - clear(); // clear previous scene - if (_vm->isM4() || (_vm->getGameType() == GType_RexNebular)) { char resourceName[20]; Common::SeekableReadStream *stream; @@ -752,7 +864,7 @@ void M4Surface::scrollX(int xAmount) { return; byte buffer[80]; - int direction = (xAmount > 0) ? 1 : -1; + int direction = (xAmount > 0) ? -1 : 1; int xSize = ABS(xAmount); assert(xSize <= 80); @@ -817,15 +929,32 @@ void M4Surface::translate(RGBList *list, bool isTransparent) { byte *palIndexes = list->palIndexes(); for (int i = 0; i < width() * height(); ++i, ++p) { - if (!isTransparent || (*p != 0)) { - assert(*p < list->size()); - *p = palIndexes[*p]; + if (!isTransparent || (*p != TRANSPARENT_COLOUR_INDEX)) { + if (*p < list->size()) + *p = palIndexes[*p]; + else + warning("Pal index %d exceeds list size %d", *p, list->size()); } } freeData(); } +M4Surface *M4Surface::flipHorizontal() const { + M4Surface *dest = new M4Surface(width(), height()); + dest->_rgbList = (this->_rgbList == NULL) ? NULL : this->_rgbList->clone(); + + byte *destP = dest->getBasePtr(); + + for (int y = 0; y < height(); ++y) { + const byte *srcP = getBasePtr(width() - 1, y); + for (int x = 0; x < width(); ++x) + *destP++ = *srcP--; + } + + return dest; +} + //-------------------------------------------------------------------------- // Palette class // diff --git a/engines/m4/graphics.h b/engines/m4/graphics.h index 8c4b9ac072..ecb5048b26 100644 --- a/engines/m4/graphics.h +++ b/engines/m4/graphics.h @@ -40,6 +40,7 @@ namespace M4 { #define MADS_SCREEN_HEIGHT 200 #define MADS_Y_OFFSET ((MADS_SCREEN_HEIGHT - MADS_SURFACE_HEIGHT) / 2) +#define TRANSPARENT_COLOUR_INDEX 0xFF struct BGR8 { uint8 b, g, r; @@ -74,6 +75,7 @@ public: int size() { return _size; } RGB8 &operator[](int idx) { return _data[idx]; } void setRange(int start, int count, const RGB8 *src); + RGBList *clone() const; }; // M4Surface @@ -96,6 +98,7 @@ private: byte _color; bool _isScreen; RGBList *_rgbList; + bool _ownsData; void rexLoadBackground(Common::SeekableReadStream *source, RGBList **palData = NULL); void madsLoadBackground(int roomNumber, RGBList **palData = NULL); @@ -105,12 +108,24 @@ public: create(g_system->getWidth(), isScreen ? g_system->getHeight() : MADS_SURFACE_HEIGHT, 1); _isScreen = isScreen; _rgbList = NULL; + _ownsData = true; } M4Surface(int width_, int height_) { create(width_, height_, 1); _isScreen = false; _rgbList = NULL; + _ownsData = true; } + M4Surface(int width_, int height_, byte *srcPixels, int pitch_) { + bytesPerPixel = 1; + w = width_; + h = height_; + pitch = pitch_; + pixels = srcPixels; + _rgbList = NULL; + _ownsData = false; + } + virtual ~M4Surface(); // loads a .COD file into the M4Surface @@ -142,6 +157,7 @@ public: inline Common::Rect bounds() const { return Common::Rect(0, 0, width(), height()); } inline int width() const { return w; } inline int height() const { return h; } + inline int getPitch() const { return pitch; } void setSize(int sizeX, int sizeY) { create(sizeX, sizeY, 1); } inline byte *getBasePtr() { return (byte *)pixels; @@ -154,12 +170,12 @@ public: } void freeData(); void clear(); + void reset(); void frameRect(const Common::Rect &r, uint8 color); void fillRect(const Common::Rect &r, uint8 color); - void copyFrom(M4Surface *src, const Common::Rect &srcBounds, int destX, int destY, - int transparentColour = -1); - void copyFrom(M4Surface *src, int destX, int destY, int depth, M4Surface *depthSurface, int scale, - int transparentColour = -1); + void copyFrom(M4Surface *src, const Common::Rect &srcBounds, int destX, int destY, int transparentColour = -1); + void copyFrom(M4Surface *src, int destX, int destY, int depth, M4Surface *depthSurface, + int scale, int transparentColour = -1); void update() { if (_isScreen) { @@ -188,6 +204,7 @@ public: void scrollY(int yAmount); void translate(RGBList *list, bool isTransparent = false); + M4Surface *flipHorizontal() const; }; enum FadeType {FT_TO_GREY, FT_TO_COLOR, FT_TO_BLOCK}; diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp index a5db6660d8..a999a6bd5a 100644 --- a/engines/m4/m4.cpp +++ b/engines/m4/m4.cpp @@ -147,6 +147,8 @@ MadsM4Engine::~MadsM4Engine() { delete _random; delete _palette; delete _globals; + delete _sound; + delete _driver; delete _resourceManager; } @@ -154,14 +156,14 @@ Common::Error MadsM4Engine::run() { // Initialize backend _screen = new M4Surface(true); // Special form for creating screen reference - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); + bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); - MidiDriver *driver = MidiDriver::createMidi(midiDriver); + _driver = MidiDriver::createMidi(dev); if (native_mt32) - driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); + _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); - _midi = new MidiPlayer(this, driver); + _midi = new MidiPlayer(this, _driver); _midi->setGM(true); _midi->setNativeMT32(native_mt32); @@ -512,7 +514,6 @@ Common::Error MadsEngine::run() { // Set up needed common functionality MadsM4Engine::run(); - _scene = new MadsScene(this); _palette->setMadsSystemPalette(); _mouse->init("cursor.ss", NULL); @@ -536,16 +537,20 @@ Common::Error MadsEngine::run() { //for (int i = 0; i < _globals->getMessagesSize(); i++) //printf("%s\n----------\n", _globals->loadMessage(i)); - if ((getGameType() == GType_RexNebular) || (getGameType() == GType_DragonSphere)) { - loadMenu(MAIN_MENU); + if (getGameType() == GType_RexNebular) { + MadsGameLogic::initialiseGlobals(); + _scene = NULL; + loadMenu(MAIN_MENU); } else { - if (getGameType() == GType_DragonSphere) { - _scene->loadScene(FIRST_SCENE); - } else if (getGameType() == GType_Phantom) { - //_scene->loadScene(FIRST_SCENE); - _scene->loadScene(106); // a more interesting scene - } + // Test code + _scene = new MadsScene(this); + + startScene(FIRST_SCENE); + RGBList *_bgPalData; + _scene->loadBackground(FIRST_SCENE, &_bgPalData); + _palette->addRange(_bgPalData); + _scene->translate(_bgPalData); _scene->show(); @@ -564,15 +569,6 @@ Common::Error MadsEngine::run() { _viewManager->systemHotkeys().add(Common::KEYCODE_ESCAPE, &escapeHotkeyHandler); _viewManager->systemHotkeys().add(Common::KEYCODE_KP_MULTIPLY, &textviewHotkeyHandler); - // Load the general game SFX/voices - if (getGameType() == GType_RexNebular) { - _sound->loadDSRFile("rex009.dsr"); - } else if (getGameType() == GType_Phantom) { - _sound->loadDSRFile("phan009.dsr"); - } else if (getGameType() == GType_DragonSphere) { - _sound->loadDSRFile("drag009.dsr"); - } - uint32 nextFrame = g_system->getMillis(); while (!_events->quitFlag) { eventHandler(); diff --git a/engines/m4/m4.h b/engines/m4/m4.h index 9937107668..3174c886d5 100644 --- a/engines/m4/m4.h +++ b/engines/m4/m4.h @@ -29,6 +29,7 @@ #include "common/scummsys.h" #include "common/util.h" #include "common/random.h" +#include "sound/mididrv.h" #include "engines/engine.h" @@ -41,6 +42,7 @@ #include "m4/events.h" #include "m4/font.h" #include "m4/scene.h" +#include "m4/mads_player.h" #include "m4/mads_scene.h" #include "m4/m4_scene.h" #include "m4/actor.h" @@ -123,7 +125,7 @@ enum { struct M4GameDescription; -#define GAME_FRAME_DELAY 50 +#define GAME_FRAME_DELAY 20 #define VALIDATE_MADS assert(!_vm->isM4()) @@ -144,6 +146,7 @@ protected: void shutdown(); + MidiDriver *_driver; MidiPlayer *_midi; public: @@ -211,6 +214,7 @@ private: public: MadsConversation _converse; uint32 _currentTimer; + MadsPlayer _player; public: MadsEngine(OSystem *syst, const M4GameDescription *gameDesc); virtual ~MadsEngine(); @@ -219,6 +223,12 @@ public: MadsGlobals *globals() { return (MadsGlobals *)_globals; } MadsScene *scene() { return (MadsScene *)_scene; } + void startScene(int sceneNum) { + if (!_scene) + _scene = new MadsScene(this); + _scene->show(); + _scene->loadScene(101); + } }; class M4Engine : public MadsM4Engine { diff --git a/engines/m4/mads_anim.cpp b/engines/m4/mads_anim.cpp index e1dbbaf106..ca53bdca75 100644 --- a/engines/m4/mads_anim.cpp +++ b/engines/m4/mads_anim.cpp @@ -446,7 +446,7 @@ AnimviewView::AnimviewView(MadsM4Engine *vm): MadsView::_bgSurface = &_backgroundSurface; MadsView::_depthSurface = &_codeSurface; - MadsView::_yOffset = MADS_Y_OFFSET; + MadsView::setViewport(Common::Rect(0, MADS_Y_OFFSET, MADS_SURFACE_WIDTH, MADS_Y_OFFSET + MADS_SURFACE_HEIGHT)); _screenType = VIEWID_ANIMVIEW; _screenFlags.layer = LAYER_BACKGROUND; @@ -458,11 +458,19 @@ AnimviewView::AnimviewView(MadsM4Engine *vm): _previousUpdate = 0; _transition = kTransitionNone; _activeAnimation = NULL; + _bgLoadFlag = true; + _startFrame = -1; + _scriptDone = false; + reset(); // Set up system palette colors _vm->_palette->setMadsSystemPalette(); + // Block reserved palette ranges + _vm->_palette->blockRange(16, 2); + _vm->_palette->blockRange(250, 4); + clear(); _backgroundSurface.clear(); @@ -510,7 +518,9 @@ bool AnimviewView::onEvent(M4EventType eventType, int32 param, int x, int y, boo } void AnimviewView::updateState() { - if (!_script) + MadsView::update(); + + if (!_script || _scriptDone) return; if (!_activeAnimation) { @@ -524,19 +534,35 @@ void AnimviewView::updateState() { delete _activeAnimation; _activeAnimation = NULL; - if (_script->eos() || _script->err()) { + // Clear up current background and sprites + _backgroundSurface.reset(); + clearLists(); + + // Reset flags + _startFrame = -1; + + readNextCommand(); + + // Check if script is finished + if (_scriptDone) { scriptDone(); return; } - - readNextCommand(); } refresh(); } void AnimviewView::readNextCommand() { +static bool tempFlag = true;//****DEBUG - Temporarily allow me to skip several intro scenes **** + while (!_script->eos() && !_script->err()) { + if (!tempFlag) { + tempFlag = true; + strncpy(_currentLine, _script->readLine().c_str(), 79); + strncpy(_currentLine, _script->readLine().c_str(), 79); + } + strncpy(_currentLine, _script->readLine().c_str(), 79); // Process any switches on the line @@ -564,15 +590,24 @@ void AnimviewView::readNextCommand() { break; } + if (!_currentLine[0]) { + // A blank line at this point means that the end of the animation has been reached + _scriptDone = true; + return; + } + if (strchr(_currentLine, '.') == NULL) strcat(_currentLine, ".aa"); + uint16 flags = 0; + if (_bgLoadFlag) + flags |= 0x100; + _activeAnimation = new MadsAnimation(_vm, this); - _activeAnimation->load(_currentLine, 0); + _activeAnimation->initialise(_currentLine, flags, &_backgroundSurface, &_codeSurface); - _backgroundSurface.loadBackground(_activeAnimation->roomNumber()); - _codeSurface.setSize(_backgroundSurface.width(), _backgroundSurface.height()); - _codeSurface.fillRect(_codeSurface.bounds(), 0xff); + if (_startFrame != -1) + _activeAnimation->setCurrentFrame(_startFrame); _spriteSlots.fullRefresh(); /* @@ -627,6 +662,7 @@ return; Switches are: (taken from the help of the original executable) -b Toggle background load status off/on. -c:char Specify sound card id letter. + -f:num Specify a specific starting frame number -g Stay in graphics mode on exit. -h[:ex] Disable EMS/XMS high memory support. -i Switch sound interrupts mode off/on. @@ -670,18 +706,39 @@ void AnimviewView::processCommand() { str_upper(commandStr); char *param = commandStr; - if (!strncmp(commandStr, "X", 1)) { - //printf("X "); - } else if (!strncmp(commandStr, "W", 1)) { - //printf("W "); - } else if (!strncmp(commandStr, "R", 1)) { - param = param + 2; - //printf("R:%s ", param); - } else if (!strncmp(commandStr, "O", 1)) { + switch (commandStr[0]) { + case 'B': + // Toggle background load flag + _bgLoadFlag = !_bgLoadFlag; + break; + + case 'F': + // Start animation at a specific frame + ++param; + assert(*param == ':'); + _startFrame = atoi(++param); + break; + + case 'O': param = param + 2; //printf("O:%i ", atoi(param)); _transition = atoi(param); - } else { + break; + + case 'R': + param = param + 2; + //printf("R:%s ", param); + break; + + case 'W': + //printf("W "); + break; + + case 'X': + //printf("X "); + break; + + default: error("Unknown response command: '%s'", commandStr); } } diff --git a/engines/m4/mads_anim.h b/engines/m4/mads_anim.h index 8c4a5e6fb7..b33ea24071 100644 --- a/engines/m4/mads_anim.h +++ b/engines/m4/mads_anim.h @@ -81,6 +81,7 @@ class AnimviewView : public View, MadsView { private: char _resourceName[80]; Common::SeekableReadStream *_script; + bool _scriptDone; uint32 _previousUpdate; char _currentLine[80]; M4Surface _backgroundSurface; @@ -90,6 +91,8 @@ private: RGBList *_palData; int _transition; MadsAnimation *_activeAnimation; + bool _bgLoadFlag; + int _startFrame; void reset(); void readNextCommand(); diff --git a/engines/m4/mads_logic.cpp b/engines/m4/mads_logic.cpp index 9cb053a876..e451a306ef 100644 --- a/engines/m4/mads_logic.cpp +++ b/engines/m4/mads_logic.cpp @@ -29,6 +29,114 @@ namespace M4 { +void MadsGameLogic::initialiseGlobals() { + // Clear the entire globals list + Common::set_to(&_madsVm->globals()->_globals[0], &_madsVm->globals()->_globals[TOTAL_NUM_VARIABLES], 0); + + SET_GLOBAL(4, 8); + SET_GLOBAL(33, 1); + SET_GLOBAL(10, 0xFFFF); + SET_GLOBAL(13, 0xFFFF); + SET_GLOBAL(15, 0xFFFF); + SET_GLOBAL(19, 0xFFFF); + SET_GLOBAL(20, 0xFFFF); + SET_GLOBAL(21, 0xFFFF); + SET_GLOBAL(95, 0xFFFF); + + // TODO: unknown sub call + + // Put the values 0 through 3 in a random ordering in global slots 83 - 86 + for (int idx = 0; idx < 4; ) { + int randVal = _madsVm->_random->getRandomNumber(4); + SET_GLOBAL(83 + idx, randVal); + + // Check whether the given value has already been used + bool flag = false; + for (int idx2 = 0; idx2 < idx; ++idx2) { + if (randVal == GET_GLOBAL(83 + idx2)) + flag = true; + } + + if (!flag) + ++idx; + } + + // Put the values 0 through 3 in a random ordering in global slots 87 - 90 + for (int idx = 0; idx < 4; ) { + int randVal = _madsVm->_random->getRandomNumber(3); + SET_GLOBAL(87 + idx, randVal); + + // Check whether the given value has already been used + bool flag = false; + for (int idx2 = 0; idx2 < idx; ++idx2) { + if (randVal == GET_GLOBAL(87 + idx2)) + flag = true; + } + + if (!flag) + ++idx; + } + + // Miscellaneous global settings + SET_GLOBAL(120, 501); + SET_GLOBAL(121, 0xFFFF); + SET_GLOBAL(110, 0xFFFF); + SET_GLOBAL(119, 1); + SET_GLOBAL(134, 4); + SET_GLOBAL(190, 201); + SET_GLOBAL(191, 301); + SET_GLOBAL(192, 413); + SET_GLOBAL(193, 706); + SET_GLOBAL(194, 801); + SET_GLOBAL(195, 551); + SET_GLOBAL(196, 752); + + // Fill out the globals 200 - 209 with unique random number values less than 10000 + for (int idx = 0; idx < 10; ) { + int randVal = _madsVm->_random->getRandomNumber(9999); + SET_GLOBAL(200 + idx, randVal); + + // Check whether the given value has already been used + bool flag = false; + for (int idx2 = 0; idx2 < idx; ++idx2) { + if (randVal == GET_GLOBAL(87 + idx2)) + flag = true; + } + + if (!flag) + ++idx; + } + + switch (_madsVm->globals()->_difficultyLevel) { + case 1: + // Very hard + SET_GLOBAL(35, 0); + // TODO: object set room + SET_GLOBAL(137, 5); + SET_GLOBAL(136, 0); + break; + + case 2: + // Hard + SET_GLOBAL(35, 0); + // TODO: object set room + SET_GLOBAL(136, 0xFFFF); + SET_GLOBAL(137, 6); + break; + + case 3: + // Easy + SET_GLOBAL(35, 2); + // TODO: object set room + break; + } + + _madsVm->_player._direction = 8; + _madsVm->_player._newDirection = 8; + + // TODO: unknown processing routine getting called for 'RXM' and 'ROX' +} + /*--------------------------------------------------------------------------*/ const char *MadsSceneLogic::formAnimName(char sepChar, int16 suffixNum) { @@ -54,7 +162,7 @@ void MadsSceneLogic::getSceneSpriteSet() { strcpy(prefix, ""); _madsVm->globals()->playerSpriteChanged = true; - _madsVm->scene()->loadPlayerSprites(prefix); + _madsVm->_player.loadSprites(prefix); // if ((_sceneNumber == 105) ((_sceneNumber == 109) && (word_84800 != 0))) // _madsVm->globals()->playerSpriteChanged = true; @@ -69,6 +177,10 @@ void MadsSceneLogic::getAnimName() { strcpy(_madsVm->scene()->_aaName, newName); } +IntStorage &MadsSceneLogic::dataMap() { + return _madsVm->globals()->_dataMap; +} + /*--------------------------------------------------------------------------*/ uint16 MadsSceneLogic::loadSpriteSet(uint16 suffixNum, uint16 sepChar) { @@ -146,6 +258,59 @@ void MadsSceneLogic::lowRoomsEntrySound() { } } +void MadsSceneLogic::getPlayerSpritesPrefix() { + _madsVm->_sound->playSound(5); + + char oldName[80]; + strcpy(oldName, _madsVm->_player._spritesPrefix); + + if ((_madsVm->globals()->_nextSceneId <= 103) || (_madsVm->globals()->_nextSceneId == 111)) + strcpy(_madsVm->_player._spritesPrefix, (_madsVm->globals()->_globals[0] == SEX_FEMALE) ? "ROX" : "RXM"); + else if (_madsVm->globals()->_nextSceneId <= 110) + strcpy(_madsVm->_player._spritesPrefix, "RXSM"); + else if (_madsVm->globals()->_nextSceneId == 112) + strcpy(_madsVm->_player._spritesPrefix, ""); + + if (strcmp(oldName, _madsVm->_player._spritesPrefix) != 0) + _madsVm->_player._spritesChanged = true; + + if ((_madsVm->globals()->_nextSceneId == 105) || + ((_madsVm->globals()->_nextSceneId == 109) && (_madsVm->globals()->_globals[15] != 0))) { + // TODO: unknown flag setting + _madsVm->_player._spritesChanged = true; + } + + _madsVm->_palette->setEntry(16, 40, 255, 255); + _madsVm->_palette->setEntry(17, 40, 180, 180); + +} + +void MadsSceneLogic::getPlayerSpritesPrefix2() { + _madsVm->_sound->playSound(5); + + char oldName[80]; + strcpy(oldName, _madsVm->_player._spritesPrefix); + + if ((_madsVm->globals()->_nextSceneId == 213) || (_madsVm->globals()->_nextSceneId == 216)) + strcpy(_madsVm->_player._spritesPrefix, ""); + else if (_madsVm->globals()->_globals[0] == SEX_MALE) + strcpy(_madsVm->_player._spritesPrefix, "RXM"); + else + strcpy(_madsVm->_player._spritesPrefix, "ROX"); + + // TODO: unknown flag setting for next scene Id > 212 + + if (strcmp(oldName, _madsVm->_player._spritesPrefix) != 0) + _madsVm->_player._spritesChanged = true; + +/* if ((_madsVm->globals()->_nextSceneId == 203) && (_madsVm->globals()->_nextSceneId == 204) && + (_madsVm->globals()->_globals[0x22] == 0)) + // TODO: unknown flag set +*/ + _madsVm->_palette->setEntry(16, 40, 255, 255); + _madsVm->_palette->setEntry(17, 40, 180, 180); +} + /*--------------------------------------------------------------------------*/ @@ -171,7 +336,9 @@ void MadsSceneLogic::setupScene() { // sub_1e754(animName, 3); if ((_sceneNumber >= 101) && (_sceneNumber <= 112)) - getSceneSpriteSet(); + getPlayerSpritesPrefix(); + else + getPlayerSpritesPrefix2(); getAnimName(); } @@ -192,7 +359,7 @@ void MadsSceneLogic::enterScene() { _spriteIndexes[16] = startCycledSpriteSequence(_spriteIndexes[1], 0, 4, 0, 1, 0); _spriteIndexes[17] = startCycledSpriteSequence(_spriteIndexes[2], 0, 4, 0, 1, 0); -// _madsVm->scene()->_sequenceList.addSubEntry(_spriteIndexes[17], SM_FRAME_INDEX, 7, 70); + _madsVm->scene()->_sequenceList.addSubEntry(_spriteIndexes[17], SM_FRAME_INDEX, 7, 70); _spriteIndexes[18] = startReversibleSpriteSequence(_spriteIndexes[3], 0, 10, 0, 0, 60); _spriteIndexes[19] = startCycledSpriteSequence(_spriteIndexes[4], 0, 5, 0, 1, 0); @@ -208,15 +375,15 @@ void MadsSceneLogic::enterScene() { if (_madsVm->globals()->previousScene != -1) _madsVm->globals()->_globals[10] = 0; if (_madsVm->globals()->previousScene != -2) { - _madsVm->scene()->getSceneResources().playerPos = Common::Point(100, 152); + _madsVm->_player._playerPos = Common::Point(100, 152); } if ((_madsVm->globals()->previousScene == 112) || ((_madsVm->globals()->previousScene != -2) && (_spriteIndexes[29] != 0))) { // Returning from probe cutscene? _spriteIndexes[29] = -1; - _madsVm->scene()->getSceneResources().playerPos = Common::Point(161, 123); - _madsVm->scene()->getSceneResources().playerDir = 9; + _madsVm->_player._playerPos = Common::Point(161, 123); + _madsVm->_player._direction = 9; // TODO: Extra flags setting _spriteIndexes[25] = startCycledSpriteSequence(_spriteIndexes[10], 0, 3, 0, 0, 0); @@ -235,13 +402,19 @@ void MadsSceneLogic::enterScene() { if (_madsVm->globals()->_globals[10]) { const char *animName = MADSResourceManager::getResourceName('S', 'e', EXTTYPE_AA, NULL, -1); - _madsVm->scene()->loadAnimation(animName, 0x47); + _madsVm->scene()->loadAnimation(animName, 71); + + _madsVm->_player._playerPos = Common::Point(68, 140); + _madsVm->_player._direction = 4; + _madsVm->_player._visible = false; + _madsVm->_player._stepEnabled = false; - _madsVm->scene()->getSceneResources().playerPos = Common::Point(68, 140); - _madsVm->scene()->getSceneResources().playerDir = 4; - // TODO: Flags setting + dataMap()[0x56FC] = 0; + dataMap()[0x5482] = 0; + dataMap()[0x5484] = 30; } + _madsVm->globals()->_dataMap[0x5486] = 0; lowRoomsEntrySound(); } @@ -250,14 +423,66 @@ void MadsSceneLogic::doAction() { } void MadsSceneLogic::sceneStep() { - // FIXME: Temporary code to display a message on-screen - static bool tempBool = false; - if (!tempBool) { - tempBool = true; - - _madsVm->scene()->_kernelMessages.add(Common::Point(63, 100), 0x1110, 0, 0, 240, - _madsVm->globals()->getQuote(49)); + // TODO: Sound handling + + switch (_madsVm->scene()->_abortTimers) { + case 70: + _madsVm->_sound->playSound(9); + break; + case 71: + _madsVm->globals()->_globals[10] = 0; + _madsVm->_player._visible = true; + _madsVm->_player._stepEnabled = true; + + _madsVm->_player._priorTimer = _madsVm->_currentTimer - _madsVm->_player._ticksAmount; + break; + case 72: + case 73: + // TODO: Method that should be scripted + break; + + default: + break; } + + // Wake up message sequence + Animation *anim = _madsVm->scene()->activeAnimation(); + if (anim) { + if ((anim->getCurrentFrame() == 6) && (dataMap()[0x5482] == 0)) { + dataMap()[0x5482]++; + _madsVm->scene()->_kernelMessages.add(Common::Point(63, dataMap()[0x5484]), + 0x1110, 0, 0, 240, _madsVm->globals()->getQuote(49)); + dataMap()[0x5484] += 14; + } + + if ((anim->getCurrentFrame() == 7) && (dataMap()[0x5482] == 1)) { + dataMap()[0x5482]++; + _madsVm->scene()->_kernelMessages.add(Common::Point(63, dataMap()[0x5484]), + 0x1110, 0, 0, 240, _madsVm->globals()->getQuote(54)); + dataMap()[0x5484] += 14; + } + + if ((anim->getCurrentFrame() == 10) && (dataMap()[0x5482] == 2)) { + dataMap()[0x5482]++; + _madsVm->scene()->_kernelMessages.add(Common::Point(63, dataMap()[0x5484]), + 0x1110, 0, 0, 240, _madsVm->globals()->getQuote(55)); + dataMap()[0x5484] += 14; + } + + if ((anim->getCurrentFrame() == 17) && (dataMap()[0x5482] == 3)) { + dataMap()[0x5482]++; + _madsVm->scene()->_kernelMessages.add(Common::Point(63, dataMap()[0x5484]), + 0x1110, 0, 0, 240, _madsVm->globals()->getQuote(56)); + dataMap()[0x5484] += 14; + } + + if ((anim->getCurrentFrame() == 20) && (dataMap()[0x5482] == 4)) { + dataMap()[0x5482]++; + _madsVm->scene()->_kernelMessages.add(Common::Point(63, dataMap()[0x5484]), + 0x1110, 0, 0, 240, _madsVm->globals()->getQuote(50)); + dataMap()[0x5484] += 14; + } + } } } diff --git a/engines/m4/mads_logic.h b/engines/m4/mads_logic.h index 8c3f41d08b..98d6df6163 100644 --- a/engines/m4/mads_logic.h +++ b/engines/m4/mads_logic.h @@ -42,6 +42,8 @@ private: uint16 startSpriteSequence3(uint16 srcSpriteIdx, int v0, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks); void activateHotspot(int idx, bool active); void lowRoomsEntrySound(); + void getPlayerSpritesPrefix(); + void getPlayerSpritesPrefix2(); private: int _sceneNumber; int16 _spriteIndexes[50]; @@ -50,6 +52,8 @@ private: const char *formAnimName(char sepChar, int16 suffixNum); void getSceneSpriteSet(); void getAnimName(); + + IntStorage &dataMap(); public: void selectScene(int sceneNum); @@ -59,6 +63,11 @@ public: void sceneStep(); }; +class MadsGameLogic { +public: + static void initialiseGlobals(); +}; + } #endif diff --git a/engines/m4/mads_menus.cpp b/engines/m4/mads_menus.cpp index 94894e78be..d7d9cf4150 100644 --- a/engines/m4/mads_menus.cpp +++ b/engines/m4/mads_menus.cpp @@ -163,7 +163,7 @@ bool RexMainMenuView::onEvent(M4EventType eventType, int32 param, int x, int y, if (_highlightedIndex != -1) { M4Sprite *spr = _menuItem->getFrame(_highlightedIndex); const Common::Point &pt = _menuItemPosList[_highlightedIndex]; - spr->copyTo(this, pt.x, row + pt.y, 0); + spr->copyTo(this, pt.x, row + pt.y, spr->getTransparencyIndex()); } } } else { @@ -211,10 +211,12 @@ void RexMainMenuView::updateState() { M4Sprite *spr = _menuItem->getFrame(0); itemSize = _menuItem->getFrame(0)->height(); spr->copyTo(this, _menuItemPosList[_menuItemIndex - 1].x, - _menuItemPosList[_menuItemIndex - 1].y + row + (itemSize / 2) - (spr->height() / 2), 0); + _menuItemPosList[_menuItemIndex - 1].y + row + (itemSize / 2) - (spr->height() / 2), + spr->getTransparencyIndex()); delete _menuItem; - copyTo(_bgSurface, Common::Rect(0, row, width(), row + MADS_SURFACE_HEIGHT), 0, 0); + copyTo(_bgSurface, Common::Rect(0, row, width(), row + MADS_SURFACE_HEIGHT), 0, 0, + spr->getTransparencyIndex()); } // Get the next sprite set @@ -275,7 +277,7 @@ void RexMainMenuView::updateState() { _bgSurface->copyTo(this, 0, row); M4Sprite *spr = _menuItem->getFrame(_frameIndex); spr->copyTo(this, _menuItemPosList[_menuItemIndex - 1].x, _menuItemPosList[_menuItemIndex - 1].y + - row + (itemSize / 2) - (spr->height() / 2), 0); + row + (itemSize / 2) - (spr->height() / 2), spr->getTransparencyIndex()); } int RexMainMenuView::getHighlightedItem(int x, int y) { @@ -293,7 +295,7 @@ int RexMainMenuView::getHighlightedItem(int x, int y) { } void RexMainMenuView::handleAction(MadsGameAction action) { - MadsM4Engine *vm = _vm; + MadsEngine *vm = (MadsEngine *)_vm; vm->_mouse->cursorOff(); vm->_viewManager->deleteView(this); @@ -303,8 +305,7 @@ void RexMainMenuView::handleAction(MadsGameAction action) { // Load a sample starting scene - note that, currently, calling loadScene automatically // removes this menu screen from being displayed vm->_mouse->cursorOn(); - vm->_scene->show(); - vm->_scene->loadScene(101); + vm->startScene(101); return; case SHOW_INTRO: @@ -325,7 +326,7 @@ void RexMainMenuView::handleAction(MadsGameAction action) { // Activate the scene display with the specified scene bool altAdvert = vm->_random->getRandomNumber(1000) >= 500; - vm->_scene->loadScene(altAdvert ? 995 : 996); + vm->startScene(altAdvert ? 995 : 996); vm->_viewManager->addView(vm->_scene); vm->_viewManager->refreshAll(); @@ -532,7 +533,7 @@ void DragonMainMenuView::updateState() { _itemPalData.push_back(palData); spr = _menuItem->getFrame(1); - spr->copyTo(this, spr->xOffset - 140, spr->yOffset - spr->height(), (int)spr->getTransparentColor()); + spr->copyTo(this, spr->xOffset - 140, spr->yOffset - spr->height(), spr->getTransparencyIndex()); _vm->_mouse->cursorOn(); } diff --git a/engines/m4/mads_player.cpp b/engines/m4/mads_player.cpp new file mode 100644 index 0000000000..8531a3ed44 --- /dev/null +++ b/engines/m4/mads_player.cpp @@ -0,0 +1,454 @@ +/* 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 "m4/m4.h" +#include "m4/mads_player.h" +#include "m4/mads_scene.h" + +namespace M4 { + +const int MadsPlayer::_directionListIndexes[32] = { + 0, 7, 4, 3, 6, 0, 2, 5, 0, 1, 9, 4, 1, 2, 7, 9, 3, 8, 9, 6, 7, 2, 3, 6, 1, 7, 9, 4, 7, 8, 0, 0 +}; + +MadsPlayer::MadsPlayer() { + _playerPos = Common::Point(160, 78); + _direction = 0; + _newDirection = 0; + _forceRefresh = true; + _stepEnabled = true; + _ticksAmount = 3; + _priorTimer = 0; + _visible = true; + _priorVisible = false; + _visible3 = false; + _yScale = 0; + _moving = false; + _spriteListStart = 0; + _spriteListIdx = 0; + _spritesChanged = true; + _currentScale = 0; + strcpy(_spritesPrefix, ""); + for (int idx = 0; idx < 8; ++idx) + _spriteSetsPresent[idx] = false; + _frameNum = 0; + _frameOffset = 0; + _unk1 = 0; + _frameCount = 0; + _frameListIndex = 0; + _actionIndex = 0; + resetActionList(); +} + +/** + * Loads the sprite set for the player + */ +bool MadsPlayer::loadSprites(const char *prefix) { + const char suffixList[8] = { '8', '9', '6', '3', '2', '7', '4', '1' }; + char setName[80]; + bool result = true; + + if (prefix) + strcpy(_spritesPrefix, prefix); + + _spriteSetCount = 0; + int prefixLen = strlen(_spritesPrefix); + + if (prefixLen == 0) { + // No player sprites at at all + for (int idx = 0; idx < 8; ++idx) + _spriteSetsPresent[idx] = false; + } else { + strcpy(setName, "*"); + strcat(setName, _spritesPrefix); + strcat(setName, "_0.SS"); + + char *digitP = strchr(setName, '_') + 1; + + for (int idx = 0; idx < 8; ++idx) { + *digitP = suffixList[idx]; + _spriteSetsPresent[idx] = true; + + int setIndex = _madsVm->scene()->_spriteSlots.addSprites(setName, true, SPRITE_SET_CHAR_INFO); + if (setIndex < 0) { + if (idx < 5) + break; + _spriteSetsPresent[idx] = false; + } else { + ++_spriteSetCount; + } + + if (idx == 0) + _spriteListStart = setIndex; + } + + result = 0; + // TODO: Unknown flag + _spritesChanged = false; + } + + return result; +} + +/** + * Called each frame to update the display of the player + */ +void MadsPlayer::update() { + if (_forceRefresh || (_visible != _priorVisible)) { + // If there's an existing player sprite visible, flag it for expiry + int slotIndex = getSpriteSlot(); + if (slotIndex >= 0) + _madsVm->scene()->_spriteSlots[slotIndex].spriteType = EXPIRED_SPRITE; + + // Figure out the depth for the sprite + int newDepth = 1; + int yp = MIN(_playerPos.y, (int16)155); + + for (int idx = 1; idx < 15; ++idx) { + if (_madsVm->scene()->getSceneResources().depthTable[newDepth] >= yp) + newDepth = idx + 1; + } + _currentDepth = newDepth; + + // Get the scale + int newScale = getScale(_playerPos.y); + _currentScale = MIN(newScale, 100); + + if (_visible) { + // Player sprite needs to be rendered + MadsSpriteSlot slot; + slot.spriteType = FOREGROUND_SPRITE; + slot.seqIndex = PLAYER_SEQ_INDEX; + slot.spriteListIndex = _spriteListStart + _spriteListIdx; + slot.frameNumber = _frameOffset + _frameNum; + slot.xp = _playerPos.x; + slot.yp = _playerPos.y + (_yScale * newScale) / 100; + slot.depth = newDepth; + slot.scale = newScale; + + if (slotIndex >= 0) { + // Check if the existing player slot has the same details, and can be re-used + MadsSpriteSlot &s2 = _madsVm->scene()->_spriteSlots[slotIndex]; + bool equal = (s2.seqIndex == slot.seqIndex) && (s2.spriteListIndex == slot.spriteListIndex) + && (s2.frameNumber == slot.frameNumber) && (s2.xp == slot.xp) && (s2.yp == slot.yp) + && (s2.depth == slot.depth) && (s2.scale == slot.scale); + + if (equal) + // Undo the prior expiry of the player sprite + s2.spriteType = SPRITE_ZERO; + else + slotIndex = -1; + } + + if (slotIndex < 0) { + // New slot needed, so allocate one and copy the slot data + slotIndex = _madsVm->scene()->_spriteSlots.getIndex(); + _madsVm->scene()->_spriteSlots[slotIndex] = slot; + } + + // TODO: Meaning of word_844c0 block + + } + } + + _visible3 = _priorVisible = _visible; + _forceRefresh = false; +} + +/** + * Updates the animation frame for the player + */ +void MadsPlayer::updateFrame() { + SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); + assert(spriteSet._charInfo); + + if (!spriteSet._charInfo->_numEntries) { + _frameNum = 1; + } else { + _frameListIndex = _actionList[_actionIndex]; + + if (!_visible) { + _unk2 = 0; + } else { + _unk2 = _actionList2[_actionIndex]; + + if (_actionIndex > 0) + --_actionIndex; + } + + // Set the player frame number + int frameIndex = ABS(_frameListIndex); + _frameNum = (_frameListIndex <= 0) ? spriteSet._charInfo->_frameList[frameIndex] : + spriteSet._charInfo->_frameList2[frameIndex]; + + // Set next waiting period in ticks + if (frameIndex == 0) + setTicksAmount(); + else + _madsVm->_player._ticksAmount = spriteSet._charInfo->_ticksList[frameIndex]; + } +} + +void MadsPlayer::setupFrame() { + resetActionList(); + _frameOffset = 0; + _spriteListIdx = _directionListIndexes[_direction]; + if (!_spriteSetsPresent[_spriteListIdx]) { + // Direction isn't present, so use alternate direction, with entries flipped + _spriteListIdx -= 4; + _frameOffset = 0x8000; + } + + SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); + assert(spriteSet._charInfo); + _unk1 = MAX(spriteSet._charInfo->_unk1, 100); + setTicksAmount(); + + _frameCount = spriteSet._charInfo->_totalFrames; + if (_frameCount == 0) + _frameCount = spriteSet.getCount(); + + _yScale = spriteSet._charInfo->_yScale; + + if ((_frameNum <= 0) || (_frameNum > _frameCount)) + _frameNum = 1; + _forceRefresh = true; +} + +void MadsPlayer::step() { + if (_visible && _stepEnabled && !_moving && (_direction == _newDirection) && (_madsVm->_currentTimer >= GET_GLOBAL32(2))) { + if (_actionIndex == 0) { + int randVal = _vm->_random->getRandomNumber(29999); + + if (GET_GLOBAL(0) == SEX_MALE) { + switch (_direction) { + case 1: + case 3: + case 7: + case 9: + if (randVal < 200) { + queueAction(-1, 0); + queueAction(1, 0); + } + break; + + case 2: + if (randVal < 500) { + for (int i = 0; i < 10; ++i) + queueAction((randVal < 250) ? 1 : 2, 0); + } else if (randVal < 750) { + for (int i = 0; i < 5; ++i) + queueAction(1, 0); + queueAction(0, 0); + for (int i = 0; i < 5; ++i) + queueAction(2, 0); + } + break; + + case 4: + case 6: + if (randVal < 500) { + for (int i = 0; i < 10; ++i) + queueAction(1, 0); + } + break; + + case 5: + case 8: + if (randVal < 200) { + queueAction(-1, 0); + queueAction(1, 0); + } + break; + } + } + } + + SET_GLOBAL32(2, GET_GLOBAL32(2) + 6); + } + + if (GET_GLOBAL(138) == 1) { + uint32 diff = _madsVm->_currentTimer - GET_GLOBAL32(142); + if (diff > 60) { + SET_GLOBAL32(144, GET_GLOBAL32(144) + 1); + } else { + SET_GLOBAL32(144, GET_GLOBAL32(144) + diff); + } + + SET_GLOBAL32(142, _madsVm->_currentTimer); + } +} + +void MadsPlayer::nextFrame() { + if (_madsVm->_currentTimer >= (_priorTimer + _ticksAmount)) { + _priorTimer = _madsVm->_currentTimer; + + if (_moving) + move(); + else + idle(); + + // Post update logic + if (_moving) { + ++_frameNum; + if (_frameNum > _frameCount) + _frameNum = 1; + _forceRefresh = true; + } else if (!_forceRefresh) { + idle(); + } + + // Final update + update(); + } +} + +int MadsPlayer::getScale(int yp) { + MadsSceneResources &r = _madsVm->scene()->getSceneResources(); + + int scale = (r.bandsRange() == 0) ? r._maxScale : (yp - r._yBandsStart) * r.scaleRange() / r.bandsRange() + + r._minScale; + + return MIN(scale, 100); +} + +/** + * Scans through the scene's sprite slot list to find any sprite displaying the player + */ +int MadsPlayer::getSpriteSlot() { + MadsSpriteSlots &slots = _madsVm->scene()->_spriteSlots; + for (int i = 0; i < slots.startIndex; ++i) { + if ((slots[i].seqIndex == PLAYER_SEQ_INDEX) && (slots[i].spriteType >= SPRITE_ZERO)) + return i; + } + return -1; +} + +void MadsPlayer::setTicksAmount() { + SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); + assert(spriteSet._charInfo); + _madsVm->_player._ticksAmount = spriteSet._charInfo->_ticksAmount; + if (_madsVm->_player._ticksAmount == 0) + _madsVm->_player._ticksAmount = 6; +} + +void MadsPlayer::resetActionList() { + _actionList[0] = 0; + _actionList2[0] = 0; + _actionIndex = 0; + _unk2 = 0; + _unk3 = 0; +} + +int MadsPlayer::queueAction(int action1, int action2) { + SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); + assert(spriteSet._charInfo); + + if ((action1 < spriteSet._charInfo->_numEntries) && (_actionIndex < 11)) { + ++_actionIndex; + _actionList[_actionIndex] = action1; + _actionList2[_actionIndex] = action2; + return false; + } + + return true; +} + +void MadsPlayer::idle() { + if (_direction != _newDirection) { + // The direction has changed, so reset for new direction + dirChanged(); + return; + } + + SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); + assert(spriteSet._charInfo); + if (spriteSet._charInfo->_numEntries == 0) + // No entries, so exit immediately + return; + + int frameIndex = ABS(_frameListIndex); + int direction = (_frameListIndex < 0) ? -1 : 1; + + if (frameIndex >= spriteSet._charInfo->_numEntries) + // Reset back to the start of the list + _frameListIndex = 0; + else { + _frameNum += direction; + _forceRefresh = true; + + if (spriteSet._charInfo->_frameList2[frameIndex] < _frameNum) { + _unk3 = _unk2; + updateFrame(); + } + if (spriteSet._charInfo->_frameList[frameIndex] < _frameNum) { + _unk3 = _unk2; + updateFrame(); + } + } +} + +void MadsPlayer::move() { + // TODO: Handle player movement +} + +void MadsPlayer::dirChanged() { + int dirIndex = 0, dirIndex2 = 0; + int newDir = 0, newDir2 = 0; + + if (_direction != _newDirection) { + // Find the index for the given direction in the player direction list + int tempDir = _direction; + do { + ++dirIndex; + newDir += tempDir; + tempDir = _directionListIndexes[tempDir + 10]; + } while (tempDir != _newDirection); + } + + + if (_direction != _newDirection) { + // Find the index for the given direction in the player direction list + int tempDir = _direction; + do { + ++dirIndex2; + newDir2 += tempDir; + tempDir = _directionListIndexes[tempDir + 20]; + } while (tempDir != _newDirection); + } + + int diff = dirIndex - dirIndex2; + if (diff == 0) + diff = newDir - newDir2; + + _direction = (diff >= 0) ? _directionListIndexes[_direction + 20] : _directionListIndexes[_direction + 10]; + setupFrame(); + if ((_direction == _newDirection) && !_moving) + updateFrame(); + + _priorTimer += 1; +} + +} // End of namespace M4 diff --git a/engines/m4/mads_player.h b/engines/m4/mads_player.h new file mode 100644 index 0000000000..65ed9ef89c --- /dev/null +++ b/engines/m4/mads_player.h @@ -0,0 +1,88 @@ +/* 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 M4_MADS_PLAYER_H +#define M4_MADS_PLAYER_H + +#include "common/scummsys.h" + +namespace M4 { + +#define PLAYER_SEQ_INDEX -2 + +class MadsPlayer { +private: + int getScale(int yp); + int getSpriteSlot(); + void setTicksAmount(); + void resetActionList(); + int queueAction(int v0, int v1); + void idle(); + void move(); + void dirChanged(); +public: + char _spritesPrefix[16]; + int _spriteSetCount; + bool _spriteSetsPresent[8]; + Common::Point _playerPos; + Common::Point _destPos; + uint32 _priorTimer; + uint _ticksAmount; + int16 _direction, _newDirection; + bool _stepEnabled; + bool _visible, _priorVisible; + bool _visible3; + bool _forceRefresh; + int16 _currentScale; + int16 _yScale; + int16 _currentDepth; + int16 _spriteListStart, _spriteListIdx; + bool _spritesChanged; + uint16 _frameOffset, _frameNum; + bool _moving; + int _unk1; + int _frameCount; + int _frameListIndex; + int _actionIndex; + int _actionList[12]; + int _actionList2[12]; + int _unk2; + int _unk3; + + static const int _directionListIndexes[32]; +public: + MadsPlayer(); + + bool loadSprites(const char *prefix); + void update(); + void updateFrame(); + void setupFrame(); + void step(); + void nextFrame(); +}; + +} // End of namespace M4 + +#endif diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index a65224c722..e4f84aeb5a 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -55,8 +55,6 @@ MadsScene::MadsScene(MadsEngine *vm): _sceneResources(), Scene(vm, &_sceneResour MadsView::_bgSurface = Scene::_backgroundSurface; MadsView::_depthSurface = Scene::_walkSurface; _interfaceSurface = new MadsInterfaceView(vm); - for (int i = 0; i < 3; ++i) - actionNouns[i] = 0; } MadsScene::~MadsScene() { @@ -69,8 +67,10 @@ MadsScene::~MadsScene() { /** * Secondary scene loading code */ -void MadsScene::loadScene2(const char *aaName) { +void MadsScene::loadScene2(const char *aaName, int sceneNumber) { // TODO: Completely finish + _madsVm->globals()->previousScene = _madsVm->globals()->sceneNumber; + _madsVm->globals()->sceneNumber = sceneNumber; _spriteSlots.clear(); _sequenceList.clear(); @@ -117,25 +117,57 @@ void MadsScene::loadScene(int sceneNumber) { // Handle common scene setting Scene::loadScene(sceneNumber); - - _madsVm->globals()->previousScene = _madsVm->globals()->sceneNumber; - _madsVm->globals()->sceneNumber = sceneNumber; + _madsVm->globals()->_nextSceneId = sceneNumber; // Existing ScummVM code that needs to be eventually replaced with MADS code loadSceneTemporary(); + _madsVm->_player._spritesChanged = true; + _madsVm->globals()->clearQuotes(); + _dynamicHotspots.reset(); + // Signal the script engine what scene is to be active _sceneLogic.selectScene(sceneNumber); - _sceneLogic.setupScene(); // Add the scene if necessary to the list of scenes that have been visited _vm->globals()->addVisitedScene(sceneNumber); + if (_vm->getGameType() == GType_RexNebular) + _sceneLogic.setupScene(); + + // TODO: Unknown code + // Secondary scene load routine - loadScene2("*I0.AA"); + if (_vm->getGameType() == GType_RexNebular) + // Secondary scene load routine + loadScene2("*I0.AA", sceneNumber); + + _madsVm->_player.loadSprites(NULL); + + switch (_madsVm->globals()->_config.screenFades) { + case 0: + _abortTimers2 = 2; + break; + case 2: + _abortTimers2 = 21; + break; + default: + _abortTimers2 = 20; + break; + } + _abortTimers = 0; + _abortTimersMode2 = ABORTMODE_1; + // Do any scene specific setup - _sceneLogic.enterScene(); + if (_vm->getGameType() == GType_RexNebular) + _sceneLogic.enterScene(); + + // Miscellaneous player setup + _madsVm->_player._destPos = _madsVm->_player._destPos; + _madsVm->_player._newDirection = _madsVm->_player._direction; + _madsVm->_player.setupFrame(); + _madsVm->_player.updateFrame(); // Purge resources _vm->res()->purge(); @@ -236,12 +268,14 @@ void MadsScene::leftClick(int x, int y) { } void MadsScene::rightClick(int x, int y) { - // ***DEBUG*** - sample dialog display - int idx = 3; //_madsVm->_globals->messageIndexOf(0x277a); - const char *msg = _madsVm->globals()->loadMessage(idx); - Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG"); - _vm->_viewManager->addView(dlg); - _vm->_viewManager->moveToFront(dlg); + if (_vm->getGameType() == GType_RexNebular) { + // ***DEBUG*** - sample dialog display + int idx = 3; //_madsVm->_globals->messageIndexOf(0x277a); + const char *msg = _madsVm->globals()->loadMessage(idx); + Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG"); + _vm->_viewManager->addView(dlg); + _vm->_viewManager->moveToFront(dlg); + } } void MadsScene::setAction(int action, int objectId) { @@ -298,9 +332,20 @@ void MadsScene::update() { } void MadsScene::updateState() { + _madsVm->_player.update(); + + // Step through the scene _sceneLogic.sceneStep(); - _sequenceList.tick(); + _madsVm->_player.step(); + _madsVm->_player._unk3 = 0; + + if (_abortTimersMode == ABORTMODE_1) + _abortTimers = 0; + + // Handle updating the player frame + _madsVm->_player.nextFrame(); + if ((_activeAnimation) && !_abortTimers) { _activeAnimation->update(); if (((MadsAnimation *) _activeAnimation)->freeFlag()) { @@ -309,9 +354,37 @@ void MadsScene::updateState() { } } - _kernelMessages.update(); + MadsView::update(); + + // Remove the animation if it's been completed + if ((_activeAnimation) && ((MadsAnimation *)_activeAnimation)->freeFlag()) + freeAnimation(); } +/** + * Does extra work at cleaning up the animation, and then deletes it + */ +void MadsScene::freeAnimation() { + if (!_activeAnimation) + return; + + MadsAnimation *anim = (MadsAnimation *)_activeAnimation; + if (anim->freeFlag()) { + _madsVm->scene()->_spriteSlots.clear(); + _madsVm->scene()->_spriteSlots.fullRefresh(); + _madsVm->scene()->_sequenceList.scan(); + } + + if (_madsVm->_player._visible) { + _madsVm->_player._forceRefresh = true; + _madsVm->_player.update(); + } + + delete _activeAnimation; + _activeAnimation = NULL; +} + + int MadsScene::loadSceneSpriteSet(const char *setName) { char resName[100]; strcpy(resName, setName); @@ -323,27 +396,6 @@ int MadsScene::loadSceneSpriteSet(const char *setName) { return _spriteSlots.addSprites(resName); } -void MadsScene::loadPlayerSprites(const char *prefix) { - const char suffixList[8] = { '8', '9', '6', '3', '2', '7', '4', '1' }; - char setName[80]; - - strcpy(setName, "*"); - strcat(setName, prefix); - strcat(setName, "_0.SS"); - char *digitP = strchr(setName, '_') + 1; - - for (int idx = 0; idx < 8; ++idx) { - *digitP = suffixList[idx]; - - if (_vm->res()->resourceExists(setName)) { - loadSceneSpriteSet(setName); - return; - } - } - - error("Couldn't find player sprites"); -} - enum boxSprites { topLeft = 0, topRight = 1, @@ -442,12 +494,12 @@ void MadsScene::showMADSV2TextBox(char *text, int x, int y, char *faceName) { boxSprites->getFrame(bottomRight)->copyTo(_backgroundSurface, curX, curY + 1); } -void MadsScene::loadAnimation(const Common::String &animName, int v0) { +void MadsScene::loadAnimation(const Common::String &animName, int abortTimers) { if (_activeAnimation) error("Multiple active animations are not allowed"); MadsAnimation *anim = new MadsAnimation(_vm, this); - anim->load(animName.c_str(), 0); + anim->load(animName.c_str(), abortTimers); _activeAnimation = anim; } @@ -637,7 +689,7 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su if (sceneNumber > 0) { sceneName = MADSResourceManager::getResourceName(RESPREFIX_RM, sceneNumber, ".DAT"); } else { - strcat(buffer1, "*"); + strcpy(buffer1, "*"); strcat(buffer1, resName); sceneName = buffer1; // TODO: Check whether this needs to be converted to 'HAG form' } @@ -649,25 +701,41 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su // Basic scene info Common::SeekableReadStream *stream = sceneInfo.getItemStream(0); - int resSceneId = stream->readUint16LE(); - assert(resSceneId == sceneNumber); - artFileNum = stream->readUint16LE(); - drawStyle = stream->readUint16LE(); - width = stream->readUint16LE(); - height = stream->readUint16LE(); - assert((width == 320) && (height == 156)); + if (_vm->getGameType() == GType_RexNebular) { + int resSceneId = stream->readUint16LE(); + assert(resSceneId == sceneNumber); + } else { + char roomFilename[10]; + char roomFilenameExpected[10]; + sprintf(roomFilenameExpected, "*RM%d", sceneNumber); + + stream->read(roomFilename, 6); + roomFilename[6] = 0; + assert(!strcmp(roomFilename, roomFilenameExpected)); + } + + // TODO: The following is wrong for Phantom/Dragon + _artFileNum = stream->readUint16LE(); + _depthStyle = stream->readUint16LE(); + _width = stream->readUint16LE(); + _height = stream->readUint16LE(); stream->skip(24); int objectCount = stream->readUint16LE(); - - stream->skip(40); + _yBandsEnd = stream->readUint16LE(); + _yBandsStart = stream->readUint16LE(); + _maxScale = stream->readSint16LE(); + _minScale = stream->readSint16LE(); + for (int i = 0; i < DEPTH_BANDS_SIZE; ++i) + _depthBands[i] = stream->readUint16LE(); + stream->skip(2); // Load in any scene objects for (int i = 0; i < objectCount; ++i) { MadsObject rec; rec.load(stream); - objects.push_back(rec); + _objects.push_back(rec); } for (int i = 0; i < 20 - objectCount; ++i) stream->skip(48); @@ -677,25 +745,25 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su for (int i = 0; i < setCount; ++i) { char buffer2[64]; Common::String s(buffer2, 64); - setNames.push_back(s); + _setNames.push_back(s); } - + + delete stream; + // Initialise a copy of the surfaces if they weren't provided bool dsFlag = false, ssFlag = false; - int gfxSize = width * height; if (!surface) { - surface = new M4Surface(width, height); + surface = new M4Surface(_width, _height); ssFlag = true; - } - int walkSize = gfxSize; - if (drawStyle == 2) { - width >>= 2; - walkSize = width * height; - } + } else if ((_width != surface->width()) || (_height != surface->height())) + surface->setSize(_width, _height); + if (!depthSurface) { - depthSurface = new M4Surface(width, height); + depthSurface = new M4Surface(_width, _height); dsFlag = true; - } + } else if ((_width != depthSurface->width()) || (_height != depthSurface->height())) + depthSurface->setSize(_width, _height); + // For Rex Nebular, read in the scene's compressed walk surface information if (_vm->getGameType() == GType_RexNebular) { @@ -708,19 +776,32 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su byte *destP = depthSurface->getBasePtr(0, 0); const byte *srcP = walkData; byte runLength; + + // Run length encoded depth data while ((runLength = *srcP++) != 0) { - Common::set_to(destP, destP + runLength, *srcP++); - destP += runLength; + if (_depthStyle == 2) { + // 2-bit depth pixels + byte byteVal = *srcP++; + for (int byteCtr = 0; byteCtr < runLength; ++byteCtr) { + byte v = byteVal; + for (int bitCtr = 0; bitCtr < 4; ++bitCtr, v >>= 2) + *destP++ = (((v & 1) + 1) << 3) - 1; + } + } else { + // 8-bit depth pixels + Common::set_to(destP, destP + runLength, *srcP++); + destP += runLength; + } } - delete walkData; + free(walkData); delete stream; } _vm->_resourceManager->toss(sceneName); // Load the surface artwork - surface->loadBackground(sceneNumber); + surface->loadBackground(_artFileNum); // Final cleanup if (ssFlag) @@ -915,7 +996,7 @@ void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) { // Display object sprite. Note that the frame number isn't used directly, because it would result // in too fast an animation M4Sprite *spr = _objectSprites->getFrame(_objectFrameNumber / INV_ANIM_FRAME_SPEED); - spr->copyTo(destSurface, INVENTORY_X, INVENTORY_Y, 0); + spr->copyTo(destSurface, INVENTORY_X, INVENTORY_Y, TRANSPARENT_COLOUR_INDEX); if (!_madsVm->globals()->_config.invObjectsStill && !dialogVisible) { // If objects need to be animated, move to the next frame @@ -1111,9 +1192,9 @@ bool MadsInterfaceView::handleKeypress(int32 keycode) { warning("TODO: Activate sound"); break; - case Common::KEYCODE_u: - // Rotate player - warning("TODO: Rotate player"); + case Common::KEYCODE_t: + // Rotate player - This was Ctrl-U in the original, but in ScummVM Ctrl-U is a global mute key + _madsVm->_player._newDirection = _madsVm->_player._directionListIndexes[_madsVm->_player._newDirection + 10]; break; case Common::KEYCODE_v: { diff --git a/engines/m4/mads_scene.h b/engines/m4/mads_scene.h index 0269de75c8..e671dfb194 100644 --- a/engines/m4/mads_scene.h +++ b/engines/m4/mads_scene.h @@ -35,22 +35,26 @@ namespace M4 { #define INTERFACE_HEIGHT 106 class MadsInterfaceView; +#define DEPTH_BANDS_SIZE 15 + class MadsSceneResources: public SceneResources { public: - int sceneId; - int artFileNum; - int drawStyle; - int width; - int height; - Common::Array<MadsObject> objects; - Common::Array<Common::String> setNames; - - Common::Point playerPos; - int playerDir; - - MadsSceneResources() { playerDir = 0; } + int _sceneId; + int _artFileNum; + int _depthStyle; + int _width; + int _height; + Common::Array<MadsObject> _objects; + Common::Array<Common::String> _setNames; + int _yBandsStart, _yBandsEnd; + int _maxScale, _minScale; + int _depthBands[DEPTH_BANDS_SIZE]; + + MadsSceneResources() {} ~MadsSceneResources() {} void load(int sceneId, const char *resName, int v0, M4Surface *depthSurface, M4Surface *surface); + int bandsRange() const { return _yBandsEnd - _yBandsStart; } + int scaleRange() const { return _maxScale - _minScale; } }; enum MadsActionMode {ACTMODE_NONE = 0, ACTMODE_VERB = 1, ACTMODE_OBJECT = 3, ACTMODE_TALK = 6}; @@ -99,7 +103,7 @@ private: SpriteAsset *_playerSprites; void drawElements(); - void loadScene2(const char *aaName); + void loadScene2(const char *aaName, int sceneNumber); void loadSceneTemporary(); void loadSceneHotspots(int sceneNumber); void clearAction(); @@ -107,7 +111,6 @@ private: void setAction(); public: char _aaName[100]; - uint16 actionNouns[3]; public: MadsScene(MadsEngine *vm); virtual ~MadsScene(); @@ -126,9 +129,10 @@ public: virtual void updateState(); int loadSceneSpriteSet(const char *setName); - void loadPlayerSprites(const char *prefix); void showMADSV2TextBox(char *text, int x, int y, char *faceName); - void loadAnimation(const Common::String &animName, int v0); + void loadAnimation(const Common::String &animName, int abortTimers); + Animation *activeAnimation() const { return _activeAnimation; } + void freeAnimation(); MadsInterfaceView *getInterface() { return (MadsInterfaceView *)_interfaceSurface; } MadsSceneResources &getSceneResources() { return _sceneResources; } diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index c7b4f76a00..d7e6435b14 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -86,10 +86,16 @@ int MadsSpriteSlots::getIndex() { return startIndex++; } -int MadsSpriteSlots::addSprites(const char *resName) { +int MadsSpriteSlots::addSprites(const char *resName, bool suppressErrors, int flags) { + // If errors are suppressed, first check if the resource exists + if (suppressErrors) { + if (!_vm->res()->resourceExists(resName)) + return -1; + } + // Get the sprite set Common::SeekableReadStream *data = _vm->res()->get(resName); - SpriteAsset *spriteSet = new SpriteAsset(_vm, data, data->size(), resName); + SpriteAsset *spriteSet = new SpriteAsset(_vm, data, data->size(), resName, false, flags); spriteSet->translate(_madsVm->_palette); assert(spriteSet != NULL); @@ -99,6 +105,12 @@ int MadsSpriteSlots::addSprites(const char *resName) { return _sprites.size() - 1; } +int MadsSpriteSlots::addSprites(SpriteAsset *spriteSet) { + _sprites.push_back(spriteSet); + + return _sprites.size() - 1; +} + void MadsSpriteSlots::deleteSprites(int listIndex) { if (listIndex < 0) return; @@ -136,17 +148,19 @@ typedef Common::List<DepthEntry> DepthList; void MadsSpriteSlots::drawBackground() { // Draw all active sprites onto the background surface for (int i = 0; i < startIndex; ++i) { - if (_entries[i].spriteType >= 0) { + MadsSpriteSlot &slot = _entries[i]; + + if (slot.spriteType >= 0) { _owner._dirtyAreas[i].active = false; } else { _owner._dirtyAreas[i].textActive = true; - _owner._dirtyAreas.setSpriteSlot(i, _entries[i]); + _owner._dirtyAreas.setSpriteSlot(i, slot); - if (_entries[i].spriteType == BACKGROUND_SPRITE) { - SpriteAsset &spriteSet = getSprite(_entries[i].spriteListIndex); - M4Sprite *frame = spriteSet.getFrame((_entries[i].frameNumber & 0x7fff) - 1); - int xp = _entries[i].xp; - int yp = _entries[i].yp; + if (slot.spriteType == BACKGROUND_SPRITE) { + SpriteAsset &spriteSet = getSprite(slot.spriteListIndex); + M4Sprite *frame = spriteSet.getFrame((slot.frameNumber & 0x7fff) - 1); + int xp = slot.xp; + int yp = slot.yp; if (_entries[i].scale != -1) { // Adjust position based on frame size @@ -154,12 +168,13 @@ void MadsSpriteSlots::drawBackground() { yp -= frame->height() / 2; } - if (_entries[i].depth <= 1) { - // No depth, so simply copy the frame onto the background - frame->copyTo(_owner._bgSurface, xp, yp, 0); + if (slot.depth > 1) { + // Draw the frame with depth processing + _owner._bgSurface->copyFrom(frame, xp, yp, slot.depth, _owner._depthSurface, 100, + frame->getTransparencyIndex()); } else { - // Depth was specified, so draw frame using scene's depth information - frame->copyTo(_owner._bgSurface, xp, yp, _entries[i].depth, _owner._depthSurface, 100, 0); + // No depth, so simply draw the image + frame->copyTo(_owner._bgSurface, xp, yp, frame->getTransparencyIndex()); } } } @@ -170,7 +185,7 @@ void MadsSpriteSlots::drawBackground() { _owner._dirtyAreas[i].active = false; } -void MadsSpriteSlots::drawForeground(View *view, int yOffset) { +void MadsSpriteSlots::drawForeground(M4Surface *viewport) { DepthList depthList; // Get a list of sprite object depths for active objects @@ -192,14 +207,23 @@ void MadsSpriteSlots::drawForeground(View *view, int yOffset) { assert(slot.spriteListIndex < (int)_sprites.size()); SpriteAsset &spriteSet = *_sprites[slot.spriteListIndex]; - if (slot.scale < 100) { + // Get the sprite frame + int frameNumber = slot.frameNumber & 0x7fff; + bool flipped = (slot.frameNumber & 0x8000) != 0; + M4Sprite *sprite = spriteSet.getFrame(frameNumber - 1); + + M4Surface *spr = sprite; + if (flipped) { + // Create a flipped copy of the sprite temporarily + spr = sprite->flipHorizontal(); + } + + if ((slot.scale < 100) && (slot.scale != -1)) { // Minimalised drawing - assert(slot.spriteListIndex < (int)_sprites.size()); - M4Sprite *spr = spriteSet.getFrame((slot.frameNumber & 0x7fff) - 1); - spr->copyTo(view, slot.xp, slot.yp + yOffset, slot.depth, _owner._depthSurface, slot.scale, 0); + viewport->copyFrom(spr, slot.xp, slot.yp, slot.depth, _owner._depthSurface, slot.scale, + sprite->getTransparencyIndex()); } else { int xp, yp; - M4Sprite *spr = spriteSet.getFrame(slot.frameNumber - 1); if (slot.scale == -1) { xp = slot.xp - _owner._posAdjust.x; @@ -211,12 +235,16 @@ void MadsSpriteSlots::drawForeground(View *view, int yOffset) { if (slot.depth > 1) { // Draw the frame with depth processing - spr->copyTo(view, xp, yp + yOffset, slot.depth, _owner._depthSurface, 100, 0); + viewport->copyFrom(spr, xp, yp, slot.depth, _owner._depthSurface, 100, sprite->getTransparencyIndex()); } else { // No depth, so simply draw the image - spr->copyTo(view, xp, yp + yOffset, 0); + spr->copyTo(viewport, xp, yp, sprite->getTransparencyIndex()); } } + + // Free sprite if it was a flipped one + if (flipped) + delete spr; } } @@ -270,6 +298,7 @@ MadsTextDisplay::MadsTextDisplay(MadsView &owner): _owner(owner) { for (int i = 0; i < TEXT_DISPLAY_SIZE; ++i) { MadsTextDisplayEntry rec; rec.active = false; + rec.expire = 0; _entries.push_back(rec); } } @@ -307,7 +336,7 @@ int MadsTextDisplay::add(int xp, int yp, uint fontColour, int charSpacing, const void MadsTextDisplay::setDirtyAreas() { // Determine dirty areas for active text areas for (uint idx = 0, dirtyIdx = DIRTY_AREAS_TEXT_DISPLAY_IDX; dirtyIdx < DIRTY_AREAS_SIZE; ++idx, ++dirtyIdx) { - if ((_entries[idx].expire < 0) || !_entries[idx].active) + if ((_entries[idx].expire >= 0) || !_entries[idx].active) _owner._dirtyAreas[dirtyIdx].active = false; else { _owner._dirtyAreas[dirtyIdx].textActive = true; @@ -326,23 +355,15 @@ void MadsTextDisplay::setDirtyAreas2() { } } -void MadsTextDisplay::draw(View *view, int yOffset) { +void MadsTextDisplay::draw(M4Surface *view) { for (uint idx = 0; idx < _entries.size(); ++idx) { if (_entries[idx].active && (_entries[idx].expire >= 0)) { _entries[idx].font->setColours(_entries[idx].colour1, _entries[idx].colour2, 0); _entries[idx].font->writeString(view, _entries[idx].msg, - _entries[idx].bounds.left, _entries[idx].bounds.top + yOffset, _entries[idx].bounds.width(), + _entries[idx].bounds.left, _entries[idx].bounds.top, _entries[idx].bounds.width(), _entries[idx].spacing); } } - - // Clear up any now text display entries that are to be expired - for (uint idx = 0; idx < _entries.size(); ++idx) { - if (_entries[idx].expire < 0) { - _entries[idx].active = false; - _entries[idx].expire = 0; - } - } } /** @@ -403,17 +424,17 @@ int MadsKernelMessageList::add(const Common::Point &pt, uint fontColour, uint8 f rec.abortMode = _owner._abortTimersMode2; for (int i = 0; i < 3; ++i) - rec.actionNouns[i] = _madsVm->scene()->actionNouns[i]; + rec.actionNouns[i] = _madsVm->globals()->actionNouns[i]; - if (flags & KMSG_OWNER_TIMEOUT) - rec.frameTimer = _owner._ticksAmount + _owner._newTimeout; + if (flags & KMSG_PLAYER_TIMEOUT) + rec.frameTimer = _madsVm->_player._ticksAmount + _madsVm->_player._priorTimer; return idx; } int MadsKernelMessageList::addQuote(int quoteId, int abortTimers, uint32 timeout) { const char *quoteStr = _madsVm->globals()->getQuote(quoteId); - return add(Common::Point(0, 0), 0x1110, KMSG_OWNER_TIMEOUT | KMSG_CENTER_ALIGN, abortTimers, timeout, quoteStr); + return add(Common::Point(0, 0), 0x1110, KMSG_PLAYER_TIMEOUT | KMSG_CENTER_ALIGN, abortTimers, timeout, quoteStr); } void MadsKernelMessageList::scrollMessage(int msgIndex, int numTicks, bool quoted) { @@ -429,8 +450,8 @@ void MadsKernelMessageList::scrollMessage(int msgIndex, int numTicks, bool quote _entries[msgIndex].asciiChar = *msgP; _entries[msgIndex].asciiChar2 = *(msgP + 1); - if (_entries[msgIndex].flags & KMSG_OWNER_TIMEOUT) - _entries[msgIndex].frameTimer2 = _owner._ticksAmount + _owner._newTimeout; + if (_entries[msgIndex].flags & KMSG_PLAYER_TIMEOUT) + _entries[msgIndex].frameTimer2 = _madsVm->_player._ticksAmount + _madsVm->_player._priorTimer; _entries[msgIndex].frameTimer = _entries[msgIndex].frameTimer2; } @@ -503,7 +524,7 @@ void MadsKernelMessageList::processText(int msgIndex) { if (_owner._abortTimersMode != ABORTMODE_1) { for (int i = 0; i < 3; ++i) - _madsVm->scene()->actionNouns[i] = msg.actionNouns[i]; + _madsVm->globals()->actionNouns[i] = msg.actionNouns[i]; } } } @@ -524,7 +545,7 @@ void MadsKernelMessageList::processText(int msgIndex) { } } - if (msg.flags & KMSG_OWNER_TIMEOUT) { + if (msg.flags & KMSG_PLAYER_TIMEOUT) { if (word_8469E != 0) { // TODO: Figure out various flags } else { @@ -732,9 +753,12 @@ void MadsDirtyArea::setArea(int width, int height, int maxWidth, int maxHeight) --bounds.left; ++width; } - int right = bounds.left + width; + if (bounds.left < 0) bounds.left = 0; + else if (bounds.left > maxWidth) + bounds.left = maxWidth; + int right = bounds.left + width; if (right < 0) right = 0; if (right > maxWidth) @@ -746,6 +770,8 @@ void MadsDirtyArea::setArea(int width, int height, int maxWidth, int maxHeight) if (bounds.top < 0) bounds.top = 0; + else if (bounds.top > maxHeight) + bounds.top = maxHeight; int bottom = bounds.top + height; if (bottom < 0) bottom = 0; @@ -816,6 +842,7 @@ void MadsDirtyAreas::setTextDisplay(int dirtyIdx, const MadsTextDisplayEntry &te * @param count Number of entries to process */ void MadsDirtyAreas::merge(int startIndex, int count) { +return;//***DEBUG*** if (startIndex >= count) return; @@ -855,13 +882,23 @@ void MadsDirtyAreas::mergeAreas(int idx1, int idx2) { da1.textActive = true; } -void MadsDirtyAreas::copy(M4Surface *dest, M4Surface *src, int yOffset) { +void MadsDirtyAreas::copy(M4Surface *dest, M4Surface *src, const Common::Point &posAdjust) { for (uint i = 0; i < _entries.size(); ++i) { + const Common::Rect &srcBounds = _entries[i].bounds; + + Common::Rect bounds(srcBounds.left + posAdjust.x, srcBounds.top + posAdjust.y, + srcBounds.right + posAdjust.x, srcBounds.bottom + posAdjust.y); + if (_entries[i].active && _entries[i].bounds.isValidRect()) - src->copyTo(dest, _entries[i].bounds, _entries[i].bounds.left, _entries[i].bounds.top + yOffset); + src->copyTo(dest, bounds, _entries[i].bounds.left, _entries[i].bounds.top); } } +void MadsDirtyAreas::clear() { + for (uint i = 0; i < _entries.size(); ++i) + _entries[i].active = false; +} + /*--------------------------------------------------------------------------*/ MadsSequenceList::MadsSequenceList(MadsView &owner): _owner(owner) { @@ -937,7 +974,7 @@ int MadsSequenceList::add(int spriteListIndex, int v0, int frameIndex, int trigg _entries[seqIndex].abortMode = _owner._abortTimersMode2; for (int i = 0; i < 3; ++i) - _entries[seqIndex].actionNouns[i] = _madsVm->scene()->actionNouns[i]; + _entries[seqIndex].actionNouns[i] = _madsVm->globals()->actionNouns[i]; return seqIndex; } @@ -1174,25 +1211,29 @@ MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceL _kernelMessages(*this), _spriteSlots(*this), _dirtyAreas(*this), _textDisplay(*this) { _textSpacing = -1; - _ticksAmount = 3; _newTimeout = 0; _abortTimers = 0; _abortTimers2 = 0; _abortTimersMode = ABORTMODE_0; _abortTimersMode2 = ABORTMODE_0; - _yOffset = 0; _depthSurface = NULL; _bgSurface = NULL; + _viewport = NULL; _sceneAnimation = new MadsAnimation(_vm, this); } MadsView::~MadsView() { delete _sceneAnimation; + delete _viewport; } void MadsView::refresh() { + if (!_viewport) + setViewport(_view->bounds()); + // Draw any sprites + _dirtyAreas.clear(); _spriteSlots.drawBackground(); // Process dirty areas @@ -1202,7 +1243,7 @@ void MadsView::refresh() { _dirtyAreas.merge(1, DIRTY_AREAS_SIZE); // Copy dirty areas to the main display surface - _dirtyAreas.copy(_view, _bgSurface, _yOffset); + _dirtyAreas.copy(_viewport, _bgSurface, _posAdjust); // Handle dirty areas for foreground objects _spriteSlots.setDirtyAreas(); @@ -1210,10 +1251,10 @@ void MadsView::refresh() { _dirtyAreas.merge(1, DIRTY_AREAS_SIZE); // Draw foreground sprites - _spriteSlots.drawForeground(_view, _yOffset); + _spriteSlots.drawForeground(_viewport); // Draw text elements onto the view - _textDisplay.draw(_view, _yOffset); + _textDisplay.draw(_viewport); // Remove any sprite slots that are no longer needed _spriteSlots.cleanUp(); @@ -1222,4 +1263,21 @@ void MadsView::refresh() { _textDisplay.cleanUp(); } +void MadsView::update() { + _sequenceList.tick(); + _kernelMessages.update(); +} + +void MadsView::clearLists() { + _textDisplay.clear(); + _kernelMessages.clear(); + _spriteSlots.clear(); +} + +void MadsView::setViewport(const Common::Rect &bounds) { + delete _viewport; + _viewport = new M4Surface(bounds.width(), bounds.height(), _view->getBasePtr(bounds.left, bounds.top), + _view->getPitch()); +} + } // End of namespace M4 diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h index 29adb7048a..0604ae1ee1 100644 --- a/engines/m4/mads_views.h +++ b/engines/m4/mads_views.h @@ -92,13 +92,14 @@ public: } int getIndex(); - int addSprites(const char *resName); + int addSprites(const char *resName, bool suppressErrors = false, int flags = 0); + int addSprites(SpriteAsset *spriteSet); void deleteSprites(int listIndex); void clear(); void deleteTimer(int seqIndex); void drawBackground(); - void drawForeground(View *view, int yOffset); + void drawForeground(M4Surface *viewport); void setDirtyAreas(); void fullRefresh(); void cleanUp(); @@ -139,7 +140,7 @@ public: int add(int xp, int yp, uint fontColour, int charSpacing, const char *msg, Font *font); void clear(); - void draw(View *view, int yOffset); + void draw(M4Surface *view); void setDirtyAreas(); void setDirtyAreas2(); void cleanUp(); @@ -148,7 +149,7 @@ public: #define TIMED_TEXT_SIZE 10 #define INDEFINITE_TIMEOUT 9999999 -enum KernelMessageFlags {KMSG_QUOTED = 1, KMSG_OWNER_TIMEOUT = 2, KMSG_SEQ_ENTRY = 4, KMSG_SCROLL = 8, KMSG_RIGHT_ALIGN = 0x10, +enum KernelMessageFlags {KMSG_QUOTED = 1, KMSG_PLAYER_TIMEOUT = 2, KMSG_SEQ_ENTRY = 4, KMSG_SCROLL = 8, KMSG_RIGHT_ALIGN = 0x10, KMSG_CENTER_ALIGN = 0x20, KMSG_EXPIRE = 0x40, KMSG_ACTIVE = 0x80}; class MadsKernelMessageEntry { @@ -170,6 +171,10 @@ public: AbortTimerMode abortMode; uint16 actionNouns[3]; char msg[100]; + + MadsKernelMessageEntry() { + flags = 0; + } }; class MadsKernelMessageList { @@ -289,7 +294,8 @@ public: void merge(int startIndex, int count); bool intersects(int idx1, int idx2); void mergeAreas(int idx1, int idx2); - void copy(M4Surface *dest, M4Surface *src, int yOffset); + void copy(M4Surface *dest, M4Surface *src, const Common::Point &posAdjust); + void clear(); }; enum SpriteAnimType {ANIMTYPE_CYCLED = 1, ANIMTYPE_REVERSIBLE = 2}; @@ -367,10 +373,11 @@ protected: public: Animation(MadsM4Engine *vm); virtual ~Animation(); - virtual void initialise(const Common::String &filename, uint16 flags, M4Surface *walkSurface, M4Surface *sceneSurface) = 0; + virtual void initialise(const Common::String &filename, uint16 flags, M4Surface *surface, M4Surface *depthSurface) = 0; virtual void load(const Common::String &filename, int v0) = 0; virtual void update() = 0; virtual void setCurrentFrame(int frameNumber) = 0; + virtual int getCurrentFrame() = 0; }; @@ -388,7 +395,6 @@ public: MadsDirtyAreas _dirtyAreas; int _textSpacing; - int _ticksAmount; uint32 _newTimeout; int _abortTimers; int8 _abortTimers2; @@ -398,12 +404,15 @@ public: M4Surface *_depthSurface; M4Surface *_bgSurface; - int _yOffset; + M4Surface *_viewport; public: MadsView(View *view); ~MadsView(); void refresh(); + void update(); + void clearLists(); + void setViewport(const Common::Rect &bounds); }; } diff --git a/engines/m4/midi.cpp b/engines/m4/midi.cpp index 78fe0d6bd6..2c767fdf5a 100644 --- a/engines/m4/midi.cpp +++ b/engines/m4/midi.cpp @@ -109,7 +109,7 @@ void MidiPlayer::send(uint32 b) { else if ((b & 0xFFF0) == 0x007BB0) { //Only respond to All Notes Off if this channel //has currently been allocated - if (_channel[b & 0x0F]) + if (!_channel[b & 0x0F]) return; } diff --git a/engines/m4/module.mk b/engines/m4/module.mk index 1b08ea2188..f60757ba3b 100644 --- a/engines/m4/module.mk +++ b/engines/m4/module.mk @@ -22,6 +22,7 @@ MODULE_OBJS = \ mads_anim.o \ mads_logic.o \ mads_menus.o \ + mads_player.o \ mads_scene.o \ mads_views.o \ midi.o \ diff --git a/engines/m4/scene.cpp b/engines/m4/scene.cpp index 15c68f276c..e78d7f865e 100644 --- a/engines/m4/scene.cpp +++ b/engines/m4/scene.cpp @@ -55,6 +55,7 @@ Scene::Scene(MadsM4Engine *vm, SceneResources *res): View(vm, Common::Rect(0, 0, Scene::~Scene() { leaveScene(); + _vm->_scene = NULL; } void Scene::loadScene(int sceneNumber) { diff --git a/engines/m4/sound.cpp b/engines/m4/sound.cpp index 69ab8c0516..e0fbd2f7a9 100644 --- a/engines/m4/sound.cpp +++ b/engines/m4/sound.cpp @@ -197,20 +197,20 @@ void Sound::loadDSRFile(const char *fileName) { //printf("DSR has %i entries\n", _dsrFile.entryCount); for (int i = 0; i < _dsrFile.entryCount; i++) { - DSREntry* newEntry = new DSREntry(); - newEntry->frequency = fileStream->readUint16LE(); - newEntry->channels = fileStream->readUint32LE(); - newEntry->compSize = fileStream->readUint32LE(); - newEntry->uncompSize = fileStream->readUint32LE(); - newEntry->offset = fileStream->readUint32LE(); + DSREntry newEntry; + newEntry.frequency = fileStream->readUint16LE(); + newEntry.channels = fileStream->readUint32LE(); + newEntry.compSize = fileStream->readUint32LE(); + newEntry.uncompSize = fileStream->readUint32LE(); + newEntry.offset = fileStream->readUint32LE(); _dsrFile.dsrEntries.push_back(newEntry); /* printf("%i: ", i); printf("frequency: %i ", newEntry->frequency); printf("channels: %i ", newEntry->channels); - printf("comp: %i ", newEntry->compSize); - printf("uncomp: %i ", newEntry->uncompSize); + printf("comp: %i ", newEntry.compSize); + printf("uncomp: %i ", newEntry.uncompSize); printf("offset: %i ", newEntry->offset); printf("\n"); */ @@ -225,9 +225,7 @@ void Sound::unloadDSRFile() { if (!_dsrFileLoaded) return; - for (int i = 0; i < _dsrFile.entryCount; i++) { - _dsrFile.dsrEntries.remove_at(0); - } + _dsrFile.dsrEntries.clear(); _dsrFile.entryCount = 0; strcpy(_dsrFile.fileName, ""); @@ -251,28 +249,28 @@ void Sound::playDSRSound(int soundIndex, int volume, bool loop) { // Get sound data FabDecompressor fab; - byte *compData = new byte[_dsrFile.dsrEntries[soundIndex]->compSize]; - byte *buffer = new byte[_dsrFile.dsrEntries[soundIndex]->uncompSize]; + byte *compData = new byte[_dsrFile.dsrEntries[soundIndex].compSize]; + byte *buffer = new byte[_dsrFile.dsrEntries[soundIndex].uncompSize]; Common::SeekableReadStream *fileStream = _vm->res()->get(_dsrFile.fileName); - fileStream->seek(_dsrFile.dsrEntries[soundIndex]->offset, SEEK_SET); - fileStream->read(compData, _dsrFile.dsrEntries[soundIndex]->compSize); + fileStream->seek(_dsrFile.dsrEntries[soundIndex].offset, SEEK_SET); + fileStream->read(compData, _dsrFile.dsrEntries[soundIndex].compSize); _vm->res()->toss(_dsrFile.fileName); - fab.decompress(compData, _dsrFile.dsrEntries[soundIndex]->compSize, - buffer, _dsrFile.dsrEntries[soundIndex]->uncompSize); + fab.decompress(compData, _dsrFile.dsrEntries[soundIndex].compSize, + buffer, _dsrFile.dsrEntries[soundIndex].uncompSize); // Play sound Audio::AudioStream *stream = Audio::makeLoopingAudioStream( Audio::makeRawStream(buffer, - _dsrFile.dsrEntries[soundIndex]->uncompSize, - _dsrFile.dsrEntries[soundIndex]->frequency, Audio::FLAG_UNSIGNED), + _dsrFile.dsrEntries[soundIndex].uncompSize, + _dsrFile.dsrEntries[soundIndex].frequency, Audio::FLAG_UNSIGNED), loop ? 0 : 1); _mixer->playStream(Audio::Mixer::kSFXSoundType, &handle->handle, stream, -1, volume); /* // Dump the sound file FILE *destFile = fopen("sound.raw", "wb"); - fwrite(_dsrFile.dsrEntries[soundIndex]->data, _dsrFile.dsrEntries[soundIndex]->uncompSize, 1, destFile); + fwrite(_dsrFile.dsrEntries[soundIndex]->data, _dsrFile.dsrEntries[soundIndex].uncompSize, 1, destFile); fclose(destFile); */ } diff --git a/engines/m4/sound.h b/engines/m4/sound.h index 7d442a73cc..5587810506 100644 --- a/engines/m4/sound.h +++ b/engines/m4/sound.h @@ -65,7 +65,7 @@ struct DSREntry { struct DSRFile { char fileName[20]; int entryCount; - Common::Array<DSREntry *> dsrEntries; + Common::Array<DSREntry> dsrEntries; }; class MadsM4Engine; diff --git a/engines/m4/sprite.cpp b/engines/m4/sprite.cpp index 0ff4bec855..641b93baea 100644 --- a/engines/m4/sprite.cpp +++ b/engines/m4/sprite.cpp @@ -121,60 +121,89 @@ void M4Sprite::loadDeltaRle(Common::SeekableReadStream* rleData, int destX, int // TODO: The sprite outlines (pixel value 0xFD) are not shown void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) { - byte *outp, *lineStart; - bool newLine = false; + bool spriteEnd = false; - outp = getBasePtr(); - lineStart = getBasePtr(); + // Set entire sprite contents to transparent pixels + fillRect(bounds(), TRANSPARENT_COLOUR_INDEX); - while (1) { - byte cmd1, cmd2, count, pixel; - - if (newLine) { - outp = lineStart + w; - lineStart = outp; - newLine = false; - } - - cmd1 = source->readByte(); + // Major line loop + for (int yp = 0; yp < h; ++yp) { + byte *destP = getBasePtr(0, yp); + bool newLine = false; + byte cmd = source->readByte(); + int x2 = 0; - if (cmd1 == 0xFC) + if (cmd == 0xfc) { + // End of entire sprite + spriteEnd = true; break; - else if (cmd1 == 0xFF) + } else if (cmd == 0xff) { + // The entire line is empty newLine = true; - else if (cmd1 == 0xFD) { - while (!newLine) { - count = source->readByte(); - if (count == 0xFF) { + } else if (cmd == 0xFD) { + // Lines contains only run lenghs of pixels + while (x2 < w) { + cmd = source->readByte(); + if (cmd == 0xff) { + // End of line reached newLine = true; - } else { - pixel = source->readByte(); - while (count--) - *outp++ = (pixel == 0xFD) ? 0 : pixel; + break; + } + + byte v = source->readByte(); + while (cmd-- > 0) { + if (x2 < w) + *destP++ = (v == 0xFD) ? TRANSPARENT_COLOUR_INDEX : v; + ++x2; } } } else { - while (!newLine) { - cmd2 = source->readByte(); - if (cmd2 == 0xFF) { + // Line intermixes run lengths with individual pixels + while (x2 < w) { + cmd = source->readByte(); + if (cmd == 0xff) { + // End of line reached newLine = true; - } else if (cmd2 == 0xFE) { - count = source->readByte(); - pixel = source->readByte(); - while (count--) - *outp++ = (pixel == 0xFD) ? 0 : pixel; + break; + } + + if (cmd == 0xFE) { + // Handle repeated sequence + cmd = source->readByte(); + byte v = source->readByte(); + while (cmd-- > 0) { + if (x2 < w) { + *destP++ = (v == 0xFD) ? TRANSPARENT_COLOUR_INDEX : v; + } + ++x2; + } } else { - *outp++ = (cmd2 == 0xFD) ? 0 : cmd2; + // Handle writing out single pixel + *destP++ = (cmd == 0xFD) ? TRANSPARENT_COLOUR_INDEX : cmd; + ++x2; } } } + + // Check if we need to scan forward to find the end of the line + if (!newLine) { + do { + if (source->eos()) { + warning("M4Sprite::loadMadsSprite: unexpected end of data"); + break; + } + } while (source->readByte() != 0xff); + } + } + + if (!spriteEnd) { + byte v = source->readByte(); + assert(v == 0xFC); } } -byte M4Sprite::getTransparentColor() const { - // FIXME: We assume that the transparent color is the color of the - // top left pixel. - return *getBasePtr(0, 0); +byte M4Sprite::getTransparencyIndex() const { + return TRANSPARENT_COLOUR_INDEX; } } // End of namespace M4 diff --git a/engines/m4/sprite.h b/engines/m4/sprite.h index 49a96a6c4a..d4e5502efd 100644 --- a/engines/m4/sprite.h +++ b/engines/m4/sprite.h @@ -115,7 +115,7 @@ public: void loadDeltaRle(Common::SeekableReadStream* rleData, int destX, int destY); void loadMadsSprite(Common::SeekableReadStream* source); - byte getTransparentColor() const; + byte getTransparencyIndex() const; protected: }; diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp index 1dfc0c3f83..dd2becd3b8 100644 --- a/engines/made/detection.cpp +++ b/engines/made/detection.cpp @@ -493,7 +493,11 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NONE + Common::GUIO_NONE, + // Maximum directory depth + 1, + // List of directory globs + 0 }; class MadeMetaEngine : public AdvancedMetaEngine { diff --git a/engines/made/made.cpp b/engines/made/made.cpp index 917141ae04..20b4dc1e1b 100644 --- a/engines/made/made.cpp +++ b/engines/made/made.cpp @@ -96,11 +96,11 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng _script = new ScriptInterpreter(this); - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); - //bool adlib = (midiDriver == MD_ADLIB); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); + bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); + //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB); - MidiDriver *driver = MidiDriver::createMidi(midiDriver); + MidiDriver *driver = MidiDriver::createMidi(dev); if (native_mt32) driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp index 149b6b6eba..5dcfff4f90 100644 --- a/engines/mohawk/console.cpp +++ b/engines/mohawk/console.cpp @@ -28,6 +28,7 @@ #include "mohawk/myst_scripts.h" #include "mohawk/graphics.h" #include "mohawk/riven.h" +#include "mohawk/riven_external.h" #include "mohawk/livingbooks.h" #include "mohawk/sound.h" #include "mohawk/video.h" @@ -307,6 +308,7 @@ RivenConsole::RivenConsole(MohawkEngine_Riven *vm) : GUI::Debugger(), _vm(vm) { DCmd_Register("dumpScript", WRAP_METHOD(RivenConsole, Cmd_DumpScript)); DCmd_Register("listZipCards", WRAP_METHOD(RivenConsole, Cmd_ListZipCards)); DCmd_Register("getRMAP", WRAP_METHOD(RivenConsole, Cmd_GetRMAP)); + DCmd_Register("combos", WRAP_METHOD(RivenConsole, Cmd_Combos)); } RivenConsole::~RivenConsole() { @@ -556,9 +558,11 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { printf ("==================================\n\n"); Common::SeekableReadStream *cardStream = _vm->getRawData(MKID_BE('CARD'), (uint16)atoi(argv[3])); cardStream->seek(4); - RivenScriptList scriptList = RivenScript::readScripts(_vm, cardStream); - for (uint32 i = 0; i < scriptList.size(); i++) + RivenScriptList scriptList = _vm->_scriptMan->readScripts(cardStream, false); + for (uint32 i = 0; i < scriptList.size(); i++) { scriptList[i]->dumpScript(varNames, xNames, 0); + delete scriptList[i]; + } delete cardStream; } else if (!scumm_stricmp(argv[2], "HSPT")) { printf ("\n\nDumping scripts for %s\'s card %d hotspots!\n", argv[1], (uint16)atoi(argv[3])); @@ -571,9 +575,11 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { for (uint16 i = 0; i < hotspotCount; i++) { printf ("Hotspot %d:\n", i); hsptStream->seek(22, SEEK_CUR); // Skip non-script related stuff - RivenScriptList scriptList = RivenScript::readScripts(_vm, hsptStream); - for (uint32 j = 0; j < scriptList.size(); j++) + RivenScriptList scriptList = _vm->_scriptMan->readScripts(hsptStream, false); + for (uint32 j = 0; j < scriptList.size(); j++) { scriptList[j]->dumpScript(varNames, xNames, 1); + delete scriptList[j]; + } } delete hsptStream; @@ -608,6 +614,33 @@ bool RivenConsole::Cmd_GetRMAP(int argc, const char **argv) { return true; } +bool RivenConsole::Cmd_Combos(int argc, const char **argv) { + // In the vain of SCUMM's 'drafts' command, this command will list + // out all combinations needed in Riven, decoded from the variables. + // You'll need to look up the Rebel Tunnel puzzle on your own; the + // solution is constant. + + uint32 teleCombo = *_vm->matchVarToString("tcorrectorder"); + uint32 prisonCombo = *_vm->matchVarToString("pcorrectorder"); + uint32 domeCombo = *_vm->matchVarToString("adomecombo"); + + DebugPrintf("Telescope Combo:\n "); + for (int i = 0; i < 5; i++) + DebugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(teleCombo, i)); + + DebugPrintf("\nPrison Combo:\n "); + for (int i = 0; i < 5; i++) + DebugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(prisonCombo, i)); + + DebugPrintf("\nDome Combo:\n "); + for (int i = 1; i <= 25; i++) + if (domeCombo & (1 << (25 - i))) + DebugPrintf("%d ", i); + + DebugPrintf("\n"); + return true; +} + LivingBooksConsole::LivingBooksConsole(MohawkEngine_LivingBooks *vm) : GUI::Debugger(), _vm(vm) { DCmd_Register("playSound", WRAP_METHOD(LivingBooksConsole, Cmd_PlaySound)); DCmd_Register("stopSound", WRAP_METHOD(LivingBooksConsole, Cmd_StopSound)); diff --git a/engines/mohawk/console.h b/engines/mohawk/console.h index 9a30d46225..1806c61027 100644 --- a/engines/mohawk/console.h +++ b/engines/mohawk/console.h @@ -88,6 +88,7 @@ private: bool Cmd_DumpScript(int argc, const char **argv); bool Cmd_ListZipCards(int argc, const char **argv); bool Cmd_GetRMAP(int argc, const char **argv); + bool Cmd_Combos(int argc, const char **argv); }; class LivingBooksConsole : public GUI::Debugger { diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp index 7f2e0cb312..f04338239f 100644 --- a/engines/mohawk/detection.cpp +++ b/engines/mohawk/detection.cpp @@ -117,882 +117,21 @@ static const PlainGameDescriptor mohawkGames[] = { {"ruff", "Ruff's Bone"}, {"newkid", "The New Kid on the Block"}, {"arthurrace", "Arthur's Reading Race"}, + {"arthurbday", "Arthur's Birthday"}, + {"lilmonster", "Little Monster at School"}, #endif {0, 0} }; +#include "mohawk/detection_tables.h" -namespace Mohawk { - -static const MohawkGameDescription gameDescriptions[] = { - // Myst - // English Windows 3.11 - // From clone2727 - { - { - "myst", - "", - AD_ENTRY1("MYST.DAT", "ae3258c9c90128d274aa6a790b3ad181"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - 0, - 0, - }, - - // Myst Demo - // English Windows 3.11 - // From CD-ROM Today July, 1994 - { - { - "myst", - "Demo", - AD_ENTRY1("DEMO.DAT", "c39303dd53fb5c4e7f3c23231c606cd0"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_MYST, - GF_DEMO, - 0, - }, - - // Myst - // German Windows 3.11 - // From clone2727 - { - { - "myst", - "", - AD_ENTRY1("MYST.DAT", "4beb3366ed3f3b9bfb6e81a14a43bdcc"), - Common::DE_DEU, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - 0, - 0, - }, - - // Myst - // German Windows 3.11 - // From LordHoto - { - { - "myst", - "", - AD_ENTRY1("MYST.DAT", "e0937cca1ab125e48e30dc3cd5046ddf"), - Common::DE_DEU, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - 0, - 0, - }, - - // Myst - // Spanish Windows ? - // From jvprat - { - { - "myst", - "", - AD_ENTRY1("MYST.DAT", "f7e7d7ca69934f1351b5acd4fe4d44c2"), - Common::ES_ESP, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - 0, - 0, - }, - - // Myst - // Japanese Windows 3.11 - // From clone2727 - { - { - "myst", - "", - AD_ENTRY1("MYST.DAT", "032c88e3b7e8db4ca475e7b7db9a66bb"), - Common::JA_JPN, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - 0, - 0, - }, - - // Myst - // French Windows 3.11 - // From Strangerke - { - { - "myst", - "", - AD_ENTRY1("MYST.DAT", "d631d42567a941c67c78f2e491f4ea58"), - Common::FR_FRA, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - 0, - 0, - }, - - // Making of Myst - // English Windows 3.11 - // From clone2727 - { - { - "MakingOfMyst", - "", - AD_ENTRY1("MAKING.DAT", "f6387e8f0f7b8a3e42c95294315d6a0e"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MAKINGOF, - 0, - 0, - }, - - // Making of Myst - // Japanese Windows 3.11 - // From clone2727 - { - { - "MakingOfMyst", - "", - AD_ENTRY1("MAKING.DAT", "03ff62607e64419ab2b6ebf7b7bcdf63"), - Common::JA_JPN, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MAKINGOF, - 0, - 0, - }, - - // Myst Masterpiece Edition - // English Windows - // From clone2727 - { - { - "myst", - "Masterpiece Edition", - AD_ENTRY1("MYST.DAT", "c4cae9f143b5947262e6cb2397e1617e"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - GF_ME, - 0, - }, - - // Myst Masterpiece Edition - // English Windows - // From clone2727 - { - { - "myst", - "Masterpiece Edition", - AD_ENTRY1("MYST.DAT", "c4cae9f143b5947262e6cb2397e1617e"), - Common::EN_ANY, - Common::kPlatformMacintosh, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - GF_ME, - 0, - }, - - // Myst Masterpiece Edition - // German Windows - // From DrMcCoy (Included in "Myst: Die Trilogie") - { - { - "myst", - "Masterpiece Edition", - AD_ENTRY1("MYST.DAT", "f88e0ace66dbca78eebdaaa1d3314ceb"), - Common::DE_DEU, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - GF_ME, - 0, - }, - - // Myst Masterpiece Edition - // French Windows - // From gamin (Included in "Myst: La Trilogie") - { - { - "myst", - "Masterpiece Edition", - AD_ENTRY1("MYST.DAT", "aea81633b2d2ae498f09072fb87263b6"), - Common::FR_FRA, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - GF_ME, - 0, - }, - - // Riven: The Sequel to Myst - // Version 1.0 (5CD) - // From clone2727 - { - { - "riven", - "", - AD_ENTRY1("a_Data.MHK", "71145fdecbd68a0cfc292c2fbddf8e08"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_RIVEN, - 0, - 0, - }, - - // Riven: The Sequel to Myst - // Version 1.03 (5CD) - // From ST - { - { - "riven", - "", - AD_ENTRY1("a_Data.MHK", "d8ccae34a0e3c709135a73f449b783be"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_RIVEN, - 0, - 0, - }, - - // Riven: The Sequel to Myst - // Version 1.? (5CD) - // From jvprat - { - { - "riven", - "", - AD_ENTRY1("a_Data.MHK", "249e8c995d191b03ee94c892c0eac775"), - Common::ES_ESP, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_RIVEN, - 0, - 0, - }, - - // Riven: The Sequel to Myst - // Version 1.? (DVD, From "Myst 10th Anniversary Edition") - // From Clone2727 - { - { - "riven", - "DVD", - AD_ENTRY1("a_Data.MHK", "08fcaa5d5a2a01d7a5a6960f497212fe"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_RIVEN, - GF_DVD, - 0, - }, - - // Riven: The Sequel to Myst - // Version 1.0 (DVD, From "Myst: Die Trilogie") - // From DrMcCoy - { - { - "riven", - "", - AD_ENTRY1("a_Data.MHK", "a5fe1c91a6033eb6ee54b287578b74b9"), - Common::DE_DEU, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_RIVEN, - GF_DVD, - 0, - }, - - // Riven: The Sequel to Myst - // Version ? (DVD, From "Myst: La Trilogie") - // From gamin - { - { - "riven", - "", - AD_ENTRY1("a_Data.MHK", "aff2a384aaa9a0e0ec51010f708c5c04"), - Common::FR_FRA, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_RIVEN, - GF_DVD, - 0, - }, - - // Riven: The Sequel to Myst - // Version ? (Demo, From "Prince of Persia Collector's Edition") - // From Clone2727 - { - { - "riven", - "Demo", - AD_ENTRY1("a_Data.MHK", "bae6b03bd8d6eb350d35fd13f0e3139f"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_RIVEN, - GF_DEMO, - 0, - }, - -#ifdef DETECT_BRODERBUND_TITLES - { - { - "zoombini", - "", - AD_ENTRY1("ZOOMBINI.MHK", "98b758fec55104c096cfd129048be9a6"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_ZOOMBINI, - GF_HASMIDI, - 0 - }, - - { - { - "csworld", - "v3.0", - AD_ENTRY1("C2K.MHK", "605fe88380848031bbd0ff84ade6fe40"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_CSWORLD, - 0, - 0 - }, - - { - { - "csworld", - "v3.5", - AD_ENTRY1("C2K.MHK", "d4857aeb0f5e2e0c4ac556aa74f38c23"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_CSWORLD, - 0, - 0 - }, - - { - { - "csamtrak", - "", - AD_ENTRY1("AMTRAK.MHK", "2f95301f0bb950d555bb7b0e3b1b7eb1"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_CSAMTRAK, - 0, - 0 - }, - - { - { - "maggiess", - "", - AD_ENTRY1("MAGGIESS.MHK", "08f75fc8c0390e68fdada5ddb35d0355"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MAGGIESS, - 0, - 0 - }, - - { - { - "jamesmath", - "", - AD_ENTRY1("BRODER.MHK", "007299da8b2c6e8ec1cde9598c243024"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_JAMESMATH, - GF_HASMIDI, - 0 - }, - - // This is in the NEWDATA folder, so I assume it's a newer version ;) - { - { - "jamesmath", - "", - AD_ENTRY1("BRODER.MHK", "53c000938a50dca92860fd9b546dd276"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_JAMESMATH, - GF_HASMIDI, - 1 - }, - - { - { - "treehouse", - "", - AD_ENTRY1("MAINROOM.MHK", "12f51894d7f838af639ea9bf1bc8f45b"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_TREEHOUSE, - GF_HASMIDI, - 0 - }, - - { - { - "greeneggs", - "", - AD_ENTRY1("GREEN.LB", "5df8438138186f89e71299d7b4f88d06"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV3, - 0, - 0 - }, - - // 32-bit version of the previous entry - { - { - "greeneggs", - "", - AD_ENTRY1("GREEN32.LB", "5df8438138186f89e71299d7b4f88d06"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV3, - 0, - 0 - }, - - { - { - "1stdegree", - "", - AD_ENTRY1("AL236_1.MHK", "3ba145492a7b8b4dee0ef4222c5639c3"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_1STDEGREE, - GF_HASMIDI, - 0 - }, - - // In The 1st Degree - // French Windows - // From Strangerke - { - { - "1stdegree", - "", - AD_ENTRY1("AL236_1.MHK", "0e0c70b1b702b6ddca61a1192ada1282"), - Common::FR_FRA, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_1STDEGREE, - GF_HASMIDI, - 0 - }, - - { - { - "csusa", - "", - AD_ENTRY1("USAC2K.MHK", "b8c9d3a2586f62bce3a48b50d7a700e9"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_CSUSA, - 0, - 0 - }, - - { - { - "tortoise", - "Demo v1.0", - AD_ENTRY1("TORTOISE.512", "75d9a2f8339e423604a0c6e8177600a6"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "tortoise", - "Demo v1.1", - AD_ENTRY1("TORTOISE.512", "a38c99360e2bea3bfdec418469aef022"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "arthur", - "", - AD_ENTRY1("PAGES.512", "1550a361454ec452fe7d2328aac2003c"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - 0, - 0 - }, - - { - { - "arthur", - "Demo", - AD_ENTRY1("PAGES.512", "a4d68cef197af1416921ca5b2e0c1e31"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "arthur", - "Demo", - AD_ENTRY1("Bookoutline", "7e2691611ff4c7b89c05221736628059"), - Common::EN_ANY, - Common::kPlatformMacintosh, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "grandma", - "Demo v1.0", - AD_ENTRY1("PAGES.512", "95d9f4b035bf5d15c57a9189f231b0f8"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "grandma", - "Demo v1.1", - AD_ENTRY1("GRANDMA.512", "72a4d5fb1b3f06b5f75425635d42ce2e"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "grandma", - "Demo", - AD_ENTRY1("Bookoutline", "553c93891b9631d1e1d269599e1efa6c"), - Common::EN_ANY, - Common::kPlatformMacintosh, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "ruff", - "Demo", - AD_ENTRY1("RUFF.512", "2ba1aa65177c816e156db648c398d362"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "ruff", - "Demo", - AD_ENTRY1("Ruff's Bone Demo", "22553ac2ceb2a166bdf1def6ad348532"), - Common::EN_ANY, - Common::kPlatformMacintosh, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "newkid", - "Demo v1.0", - AD_ENTRY1("NEWKID.512", "2b9d94763a50d514c04a3af488934f73"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "newkid", - "Demo v1.1", - AD_ENTRY1("NEWKID.512", "41e975b7390c626f8d1058a34f9d9b2e"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "arthurrace", - "", - AD_ENTRY1("RACE.LB", "1645f36bcb36e440d928e920aa48c373"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV3, - 0, - 0 - }, - - // 32-bit version of the previous entry - { - { - "arthurrace", - "", - AD_ENTRY1("RACE32.LB", "292a05bc48c1dd9583821a4181a02ef2"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV3, - 0, - 0 - }, -#endif - - { AD_TABLE_END_MARKER, 0, 0, 0 } +static const char *directoryGlobs[] = { + "all", + "assets1", + "data", + 0 }; -////////////////////////////// -//Fallback detection -////////////////////////////// - -static const MohawkGameDescription fallbackDescs[] = { - { - { - "myst", - "unknown", - AD_ENTRY1(0, 0), - Common::UNK_LANG, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - 0, - 0 - }, - - { - { - "MakingOfMyst", - "unknown", - AD_ENTRY1(0, 0), - Common::UNK_LANG, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MAKINGOF, - 0, - 0 - }, - - { - { - "myst", - "unknown (Masterpiece Edition)", - AD_ENTRY1(0, 0), - Common::UNK_LANG, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - GF_ME, - 0 - }, - - { - { - "riven", - "unknown", - AD_ENTRY1(0, 0), - Common::UNK_LANG, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_RIVEN, - 0, - 0 - }, - - { - { - "riven", - "unknown (DVD)", - AD_ENTRY1(0, 0), - Common::UNK_LANG, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_RIVEN, - GF_DVD, - 0 - } -}; - -static const ADFileBasedFallback fileBased[] = { - { &fallbackDescs[0], { "MYST.DAT", 0 } }, - { &fallbackDescs[1], { "MAKING.DAT", 0 } }, - { &fallbackDescs[2], { "MYST.DAT", "Help.dat", 0 } }, // Help system doesn't exist in original - { &fallbackDescs[3], { "a_Data.MHK", 0 } }, - { &fallbackDescs[4], { "a_Data.MHK", "t_Data1.MHK" , 0 } }, - { 0, { 0 } } -}; - -} // End of namespace Mohawk - static const ADParams detectionParams = { // Pointer to ADGameDescription or its superset structure (const byte *)Mohawk::gameDescriptions, @@ -1011,7 +150,11 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game) - Common::GUIO_NONE + Common::GUIO_NONE, + // Maximum directory depth + 2, + // List of directory globs + directoryGlobs }; class MohawkMetaEngine : public AdvancedMetaEngine { diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h new file mode 100644 index 0000000000..7470dbf1dd --- /dev/null +++ b/engines/mohawk/detection_tables.h @@ -0,0 +1,1030 @@ +/* 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$ + * + */ + +namespace Mohawk { + +static const MohawkGameDescription gameDescriptions[] = { + // Myst + // English Windows 3.11 + // From clone2727 + { + { + "myst", + "", + AD_ENTRY1("MYST.DAT", "ae3258c9c90128d274aa6a790b3ad181"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + 0, + 0, + }, + + // Myst Demo + // English Windows 3.11 + // From CD-ROM Today July, 1994 + { + { + "myst", + "Demo", + AD_ENTRY1("DEMO.DAT", "c39303dd53fb5c4e7f3c23231c606cd0"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_MYST, + GF_DEMO, + 0, + }, + + // Myst + // German Windows 3.11 + // From clone2727 + { + { + "myst", + "", + AD_ENTRY1("MYST.DAT", "4beb3366ed3f3b9bfb6e81a14a43bdcc"), + Common::DE_DEU, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + 0, + 0, + }, + + // Myst + // German Windows 3.11 + // From LordHoto + { + { + "myst", + "", + AD_ENTRY1("MYST.DAT", "e0937cca1ab125e48e30dc3cd5046ddf"), + Common::DE_DEU, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + 0, + 0, + }, + + // Myst + // Spanish Windows ? + // From jvprat + { + { + "myst", + "", + AD_ENTRY1("MYST.DAT", "f7e7d7ca69934f1351b5acd4fe4d44c2"), + Common::ES_ESP, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + 0, + 0, + }, + + // Myst + // Japanese Windows 3.11 + // From clone2727 + { + { + "myst", + "", + AD_ENTRY1("MYST.DAT", "032c88e3b7e8db4ca475e7b7db9a66bb"), + Common::JA_JPN, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + 0, + 0, + }, + + // Myst + // French Windows 3.11 + // From Strangerke + { + { + "myst", + "", + AD_ENTRY1("MYST.DAT", "d631d42567a941c67c78f2e491f4ea58"), + Common::FR_FRA, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + 0, + 0, + }, + + // Making of Myst + // English Windows 3.11 + // From clone2727 + { + { + "MakingOfMyst", + "", + AD_ENTRY1("MAKING.DAT", "f6387e8f0f7b8a3e42c95294315d6a0e"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MAKINGOF, + 0, + 0, + }, + + // Making of Myst + // Japanese Windows 3.11 + // From clone2727 + { + { + "MakingOfMyst", + "", + AD_ENTRY1("MAKING.DAT", "03ff62607e64419ab2b6ebf7b7bcdf63"), + Common::JA_JPN, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MAKINGOF, + 0, + 0, + }, + + // Myst Masterpiece Edition + // English Windows + // From clone2727 + { + { + "myst", + "Masterpiece Edition", + AD_ENTRY1("MYST.DAT", "c4cae9f143b5947262e6cb2397e1617e"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + GF_ME, + 0, + }, + + // Myst Masterpiece Edition + // English Windows + // From clone2727 + { + { + "myst", + "Masterpiece Edition", + AD_ENTRY1("MYST.DAT", "c4cae9f143b5947262e6cb2397e1617e"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + GF_ME, + 0, + }, + + // Myst Masterpiece Edition + // German Windows + // From DrMcCoy (Included in "Myst: Die Trilogie") + { + { + "myst", + "Masterpiece Edition", + AD_ENTRY1("MYST.DAT", "f88e0ace66dbca78eebdaaa1d3314ceb"), + Common::DE_DEU, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + GF_ME, + 0, + }, + + // Myst Masterpiece Edition + // French Windows + // From gamin (Included in "Myst: La Trilogie") + { + { + "myst", + "Masterpiece Edition", + AD_ENTRY1("MYST.DAT", "aea81633b2d2ae498f09072fb87263b6"), + Common::FR_FRA, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + GF_ME, + 0, + }, + + // Riven: The Sequel to Myst + // Version 1.0 (5CD) + // From clone2727 + { + { + "riven", + "", + AD_ENTRY1("a_Data.MHK", "71145fdecbd68a0cfc292c2fbddf8e08"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_RIVEN, + 0, + 0, + }, + + // Riven: The Sequel to Myst + // Version 1.03 (5CD) + // From ST + { + { + "riven", + "", + AD_ENTRY1("a_Data.MHK", "d8ccae34a0e3c709135a73f449b783be"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_RIVEN, + 0, + 0, + }, + + // Riven: The Sequel to Myst + // Version 1.? (5CD) + // From jvprat + { + { + "riven", + "", + AD_ENTRY1("a_Data.MHK", "249e8c995d191b03ee94c892c0eac775"), + Common::ES_ESP, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_RIVEN, + 0, + 0, + }, + + // Riven: The Sequel to Myst + // Version 1.? (DVD, From "Myst 10th Anniversary Edition") + // From Clone2727 + { + { + "riven", + "DVD", + AD_ENTRY1("a_Data.MHK", "08fcaa5d5a2a01d7a5a6960f497212fe"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_RIVEN, + GF_DVD, + 0, + }, + + // Riven: The Sequel to Myst + // Version 1.0 (DVD, From "Myst: Die Trilogie") + // From DrMcCoy + { + { + "riven", + "", + AD_ENTRY1("a_Data.MHK", "a5fe1c91a6033eb6ee54b287578b74b9"), + Common::DE_DEU, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_RIVEN, + GF_DVD, + 0, + }, + + // Riven: The Sequel to Myst + // Version ? (DVD, From "Myst: La Trilogie") + // From gamin + { + { + "riven", + "", + AD_ENTRY1("a_Data.MHK", "aff2a384aaa9a0e0ec51010f708c5c04"), + Common::FR_FRA, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_RIVEN, + GF_DVD, + 0, + }, + + // Riven: The Sequel to Myst + // Version ? (Demo, From "Prince of Persia Collector's Edition") + // From Clone2727 + { + { + "riven", + "Demo", + AD_ENTRY1("a_Data.MHK", "bae6b03bd8d6eb350d35fd13f0e3139f"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_RIVEN, + GF_DEMO, + 0, + }, + +#ifdef DETECT_BRODERBUND_TITLES + { + { + "zoombini", + "", + AD_ENTRY1("ZOOMBINI.MHK", "98b758fec55104c096cfd129048be9a6"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_ZOOMBINI, + GF_HASMIDI, + 0 + }, + + { + { + "csworld", + "v3.0", + AD_ENTRY1("C2K.MHK", "605fe88380848031bbd0ff84ade6fe40"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_CSWORLD, + 0, + 0 + }, + + { + { + "csworld", + "v3.5", + AD_ENTRY1("C2K.MHK", "d4857aeb0f5e2e0c4ac556aa74f38c23"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_CSWORLD, + 0, + 0 + }, + + { + { + "csamtrak", + "", + AD_ENTRY1("AMTRAK.MHK", "2f95301f0bb950d555bb7b0e3b1b7eb1"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_CSAMTRAK, + 0, + 0 + }, + + { + { + "maggiess", + "", + AD_ENTRY1("MAGGIESS.MHK", "08f75fc8c0390e68fdada5ddb35d0355"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MAGGIESS, + 0, + 0 + }, + + { + { + "jamesmath", + "", + AD_ENTRY1("BRODER.MHK", "007299da8b2c6e8ec1cde9598c243024"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_JAMESMATH, + GF_HASMIDI, + 0 + }, + + // This is in the NEWDATA folder, so I assume it's a newer version ;) + { + { + "jamesmath", + "", + AD_ENTRY1("BRODER.MHK", "53c000938a50dca92860fd9b546dd276"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_JAMESMATH, + GF_HASMIDI, + 1 + }, + + { + { + "treehouse", + "", + AD_ENTRY1("MAINROOM.MHK", "12f51894d7f838af639ea9bf1bc8f45b"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_TREEHOUSE, + GF_HASMIDI, + 0 + }, + + { + { + "greeneggs", + "", + AD_ENTRY1("GREEN.LB", "5df8438138186f89e71299d7b4f88d06"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV3, + 0, + 0 + }, + + // 32-bit version of the previous entry + { + { + "greeneggs", + "", + AD_ENTRY1("GREEN32.LB", "5df8438138186f89e71299d7b4f88d06"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV3, + 0, + 0 + }, + + { + { + "1stdegree", + "", + AD_ENTRY1("AL236_1.MHK", "3ba145492a7b8b4dee0ef4222c5639c3"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_1STDEGREE, + GF_HASMIDI, + 0 + }, + + // In The 1st Degree + // French Windows + // From Strangerke + { + { + "1stdegree", + "", + AD_ENTRY1("AL236_1.MHK", "0e0c70b1b702b6ddca61a1192ada1282"), + Common::FR_FRA, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_1STDEGREE, + GF_HASMIDI, + 0 + }, + + { + { + "csusa", + "", + AD_ENTRY1("USAC2K.MHK", "b8c9d3a2586f62bce3a48b50d7a700e9"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_CSUSA, + 0, + 0 + }, + + { + { + "tortoise", + "Demo v1.0", + AD_ENTRY1("TORTOISE.512", "75d9a2f8339e423604a0c6e8177600a6"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "tortoise", + "Demo v1.1", + AD_ENTRY1("TORTOISE.512", "a38c99360e2bea3bfdec418469aef022"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "tortoise", + "Demo", + AD_ENTRY1("The Tortoise and the Hare Demo", "35d571806838667743c7c15a133e9335"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "arthur", + "", + AD_ENTRY1("PAGES.512", "1550a361454ec452fe7d2328aac2003c"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + 0, + 0 + }, + + { + { + "arthur", + "Demo", + AD_ENTRY1("PAGES.512", "a4d68cef197af1416921ca5b2e0c1e31"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "arthur", + "Demo v1.1", + AD_ENTRY1("ARTHUR.512", "f19e824e0a2f2745ed698e6aaf44f838"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "arthur", + "Demo", + AD_ENTRY1("Bookoutline", "7e2691611ff4c7b89c05221736628059"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "arthur", + "Demo", + AD_ENTRY1("Arthur's Teacher Trouble Demo", "dcbd8af6bf25854df8ad36fd13665d08"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "grandma", + "Demo v1.0", + AD_ENTRY1("PAGES.512", "95d9f4b035bf5d15c57a9189f231b0f8"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "grandma", + "Demo v1.1", + AD_ENTRY1("GRANDMA.512", "72a4d5fb1b3f06b5f75425635d42ce2e"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "grandma", + "Demo", + AD_ENTRY1("Bookoutline", "553c93891b9631d1e1d269599e1efa6c"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "grandma", + "Demo", + AD_ENTRY1("Just Grandma and Me Demo", "552d8729fa77a4a83c88283c7d79bd31"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "ruff", + "Demo", + AD_ENTRY1("RUFF.512", "2ba1aa65177c816e156db648c398d362"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "ruff", + "Demo", + AD_ENTRY1("Ruff's Bone Demo", "22553ac2ceb2a166bdf1def6ad348532"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "newkid", + "Demo v1.0", + AD_ENTRY1("NEWKID.512", "2b9d94763a50d514c04a3af488934f73"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "newkid", + "Demo v1.1", + AD_ENTRY1("NEWKID.512", "41e975b7390c626f8d1058a34f9d9b2e"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "newkid", + "Demo", + AD_ENTRY1("The New Kid on the Block Demo", "7d33237e0ea452a97f2a3acdfb9e1286"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "arthurrace", + "", + AD_ENTRY1("RACE.LB", "1645f36bcb36e440d928e920aa48c373"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV3, + 0, + 0 + }, + + // 32-bit version of the previous entry + { + { + "arthurrace", + "", + AD_ENTRY1("RACE32.LB", "292a05bc48c1dd9583821a4181a02ef2"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV3, + 0, + 0 + }, + + { + { + "arthurbday", + "Demo", + AD_ENTRY1("BIRTHDAY.512", "fb73e387cfec65c5c930db068a8f468a"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "arthurbday", + "Demo", + AD_ENTRY1("Arthur's Birthday Demo", "0d974ec635eea615475368e865f1b1c8"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "lilmonster", + "", + AD_ENTRY1("MONSTER.512", "e7b24bf8f59106b5c4df51b39eb8c0ef"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + 0, + 0 + }, + + { + { + "lilmonster", + "", + AD_ENTRY1("BookOutline", "970409f9d967d63c05e63113f8e78fe2"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + 0, + 0 + }, +#endif + + { AD_TABLE_END_MARKER, 0, 0, 0 } +}; + +////////////////////////////// +//Fallback detection +////////////////////////////// + +static const MohawkGameDescription fallbackDescs[] = { + { + { + "myst", + "unknown", + AD_ENTRY1(0, 0), + Common::UNK_LANG, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + 0, + 0 + }, + + { + { + "MakingOfMyst", + "unknown", + AD_ENTRY1(0, 0), + Common::UNK_LANG, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MAKINGOF, + 0, + 0 + }, + + { + { + "myst", + "unknown (Masterpiece Edition)", + AD_ENTRY1(0, 0), + Common::UNK_LANG, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + GF_ME, + 0 + }, + + { + { + "riven", + "unknown", + AD_ENTRY1(0, 0), + Common::UNK_LANG, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_RIVEN, + 0, + 0 + }, + + { + { + "riven", + "unknown (DVD)", + AD_ENTRY1(0, 0), + Common::UNK_LANG, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_RIVEN, + GF_DVD, + 0 + } +}; + +static const ADFileBasedFallback fileBased[] = { + { &fallbackDescs[0], { "MYST.DAT", 0 } }, + { &fallbackDescs[1], { "MAKING.DAT", 0 } }, + { &fallbackDescs[2], { "MYST.DAT", "Help.dat", 0 } }, // Help system doesn't exist in original + { &fallbackDescs[3], { "a_Data.MHK", 0 } }, + { &fallbackDescs[4], { "a_Data.MHK", "t_Data1.MHK" , 0 } }, + { 0, { 0 } } +}; + +} // End of Namespace Mohawk diff --git a/engines/mohawk/dialogs.cpp b/engines/mohawk/dialogs.cpp index c5327dbeea..c09763cbb3 100644 --- a/engines/mohawk/dialogs.cpp +++ b/engines/mohawk/dialogs.cpp @@ -30,6 +30,7 @@ #include "gui/GuiManager.h" #include "common/savefile.h" +#include "common/translation.h" namespace Mohawk { @@ -77,11 +78,11 @@ enum { }; MystOptionsDialog::MystOptionsDialog(MohawkEngine_Myst* vm) : GUI::OptionsDialog("", 120, 120, 360, 200), _vm(vm) { - _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, "Zip Mode Activated", kZipCmd, 'Z'); - _transitionsCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, "Transitions Enabled", kTransCmd, 'T'); + _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, _("~Z~ip Mode Activated"), 0, kZipCmd); + _transitionsCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, _("~T~ransitions Enabled"), 0, kTransCmd); - new GUI::ButtonWidget(this, 95, 160, 120, 25, "OK", GUI::kOKCmd, 'O'); - new GUI::ButtonWidget(this, 225, 160, 120, 25, "Cancel", GUI::kCloseCmd, 'C'); + new GUI::ButtonWidget(this, 95, 160, 120, 25, _("~O~K"), 0, GUI::kOKCmd); + new GUI::ButtonWidget(this, 225, 160, 120, 25, _("~C~ancel"), 0, GUI::kCloseCmd); } MystOptionsDialog::~MystOptionsDialog() { @@ -111,11 +112,11 @@ void MystOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, ui } RivenOptionsDialog::RivenOptionsDialog(MohawkEngine_Riven* vm) : GUI::OptionsDialog("", 120, 120, 360, 200), _vm(vm) { - _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, "Zip Mode Activated", kZipCmd, 'Z'); - _waterEffectCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, "Water Effect Enabled", kWaterCmd, 'W'); + _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, _("~Z~ip Mode Activated"), 0, kZipCmd); + _waterEffectCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, _("~W~ater Effect Enabled"), 0, kWaterCmd); - new GUI::ButtonWidget(this, 95, 160, 120, 25, "OK", GUI::kOKCmd, 'O'); - new GUI::ButtonWidget(this, 225, 160, 120, 25, "Cancel", GUI::kCloseCmd, 'C'); + new GUI::ButtonWidget(this, 95, 160, 120, 25, _("~O~K"), 0, GUI::kOKCmd); + new GUI::ButtonWidget(this, 225, 160, 120, 25, _("~C~ancel"), 0, GUI::kCloseCmd); } RivenOptionsDialog::~RivenOptionsDialog() { diff --git a/engines/mohawk/graphics.cpp b/engines/mohawk/graphics.cpp index 2ddfb47575..1974aec9c2 100644 --- a/engines/mohawk/graphics.cpp +++ b/engines/mohawk/graphics.cpp @@ -466,27 +466,22 @@ void RivenGraphics::runScheduledTransition() { // transitions were found by hacking scripts. switch (_scheduledTransition) { + case 0: // Swipe Left + case 1: // Swipe Right + case 2: // Swipe Up + case 3: // Swipe Down case 12: // Pan Left - warning ("STUB: Pan left"); - break; case 13: // Pan Right - warning ("STUB: Pan right"); - break; case 14: // Pan Up - warning ("STUB: Pan up"); - break; case 15: // Pan Down - warning ("STUB: Pan down"); - break; case 16: // Dissolve case 17: // Dissolve (tspit CARD 155) - warning ("STUB: Dissolve"); break; default: - if (_scheduledTransition < 12) - error ("Found unused transition %d", _scheduledTransition); + if (_scheduledTransition >= 4 && _scheduledTransition <= 11) + error("Found unused transition %d", _scheduledTransition); else - error ("Found unknown transition %d", _scheduledTransition); + error("Found unknown transition %d", _scheduledTransition); } // For now, just copy the image to screen without doing any transition. @@ -607,19 +602,23 @@ void RivenGraphics::showInventory() { if (_vm->getFeatures() & GF_DEMO || _vm->getCurStack() == aspit) return; - // There are three books and three vars. However, there's only - // a possible two combinations. Either you have only Atrus' - // journal or you have all three books. - // bool hasAtrusBook = *_vm->matchVarToString("aatrusbook") != 0; + // There are three books and three vars. We have three different + // combinations. At the start you have just Atrus' journal. Later, + // you get Catherine's journal and the trap book. Near the end, + // you lose the trap book and have just the two journals. + bool hasCathBook = *_vm->matchVarToString("acathbook") != 0; - // bool hasTrapBook = *_vm->matchVarToString("atrapbook") != 0; + bool hasTrapBook = *_vm->matchVarToString("atrapbook") != 0; if (!hasCathBook) { - drawInventoryImage(101, g_atrusJournalRectSolo); + drawInventoryImage(101, g_atrusJournalRect1); + } else if (!hasTrapBook) { + drawInventoryImage(101, g_atrusJournalRect2); + drawInventoryImage(102, g_cathJournalRect2); } else { - drawInventoryImage(101, g_atrusJournalRect); - drawInventoryImage(102, g_cathJournalRect); - drawInventoryImage(100, g_trapBookRect); + drawInventoryImage(101, g_atrusJournalRect3); + drawInventoryImage(102, g_cathJournalRect3); + drawInventoryImage(100, g_trapBookRect3); } _vm->_system->updateScreen(); diff --git a/engines/mohawk/resource.cpp b/engines/mohawk/resource.cpp index 62a857b90b..74efd6770f 100644 --- a/engines/mohawk/resource.cpp +++ b/engines/mohawk/resource.cpp @@ -103,7 +103,7 @@ void MohawkArchive::open(Common::SeekableReadStream *stream) { else debug (3, "Type[%02d]: Tag = \'%s\' ResTable Offset = %04x NameTable Offset = %04x", i, tag2str(_types[i].tag), _types[i].resource_table_offset, _types[i].name_table_offset); - //Resource Table + // Resource Table _mhk->seek(_rsrc.abs_offset + _types[i].resource_table_offset); _types[i].resTable.resources = _mhk->readUint16BE(); diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index c646855bc7..07b08dc220 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -29,6 +29,7 @@ #include "common/keyboard.h" #include "mohawk/graphics.h" +#include "mohawk/resource.h" #include "mohawk/riven.h" #include "mohawk/riven_external.h" #include "mohawk/riven_saveload.h" @@ -37,10 +38,12 @@ namespace Mohawk { -Common::Rect *g_atrusJournalRectSolo; -Common::Rect *g_atrusJournalRect; -Common::Rect *g_cathJournalRect; -Common::Rect *g_trapBookRect; +Common::Rect *g_atrusJournalRect1; +Common::Rect *g_atrusJournalRect2; +Common::Rect *g_cathJournalRect2; +Common::Rect *g_atrusJournalRect3; +Common::Rect *g_cathJournalRect3; +Common::Rect *g_trapBookRect3; MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescription *gamedesc) : MohawkEngine(syst, gamedesc) { _showHotspots = false; @@ -49,20 +52,27 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio _activatedSLST = false; _ignoreNextMouseUp = false; _extrasFile = NULL; + _curStack = aspit; + _hotspots = NULL; - // Attempt to let game run from the CDs - // NOTE: assets2 contains higher quality audio than assets1 - const Common::FSNode gameDataDir(ConfMan.get("path")); + // NOTE: We can never really support CD swapping. All of the music files + // (*_Sounds.mhk) are stored on disc 1. They are copied to the hard drive + // during install and used from there. The same goes for the extras.mhk + // file. The following directories allow Riven to be played directly + // from the DVD. + const Common::FSNode gameDataDir(ConfMan.get("path")); SearchMan.addSubDirectoryMatching(gameDataDir, "all"); SearchMan.addSubDirectoryMatching(gameDataDir, "data"); SearchMan.addSubDirectoryMatching(gameDataDir, "exe"); - SearchMan.addSubDirectoryMatching(gameDataDir, "assets2"); - - g_atrusJournalRectSolo = new Common::Rect(295, 402, 313, 426); - g_atrusJournalRect = new Common::Rect(222, 402, 240, 426); - g_cathJournalRect = new Common::Rect(291, 408, 311, 419); - g_trapBookRect = new Common::Rect(363, 396, 386, 432); + SearchMan.addSubDirectoryMatching(gameDataDir, "assets1"); + + g_atrusJournalRect1 = new Common::Rect(295, 402, 313, 426); + g_atrusJournalRect2 = new Common::Rect(259, 402, 278, 426); + g_cathJournalRect2 = new Common::Rect(328, 408, 348, 419); + g_atrusJournalRect3 = new Common::Rect(222, 402, 240, 426); + g_cathJournalRect3 = new Common::Rect(291, 408, 311, 419); + g_trapBookRect3 = new Common::Rect(363, 396, 386, 432); } MohawkEngine_Riven::~MohawkEngine_Riven() { @@ -71,15 +81,17 @@ MohawkEngine_Riven::~MohawkEngine_Riven() { delete _externalScriptHandler; delete _extrasFile; delete _saveLoad; + delete _scriptMan; delete[] _vars; - delete _loadDialog; delete _optionsDialog; delete _rnd; - delete g_atrusJournalRectSolo; - delete g_atrusJournalRect; - delete g_cathJournalRect; - delete g_trapBookRect; - _cardData.scripts.clear(); + delete[] _hotspots; + delete g_atrusJournalRect1; + delete g_atrusJournalRect2; + delete g_cathJournalRect2; + delete g_atrusJournalRect3; + delete g_cathJournalRect3; + delete g_trapBookRect3; } GUI::Debugger *MohawkEngine_Riven::getDebugger() { @@ -94,9 +106,8 @@ Common::Error MohawkEngine_Riven::run() { _console = new RivenConsole(this); _saveLoad = new RivenSaveLoad(this, _saveFileMan); _externalScriptHandler = new RivenExternal(this); - _loadDialog = new GUI::SaveLoadChooser("Load Game:", "Load"); - _loadDialog->setSaveMode(false); _optionsDialog = new RivenOptionsDialog(this); + _scriptMan = new RivenScriptManager(this); _rnd = new Common::RandomSource(); g_eventRec.registerRandomSource(*_rnd, "riven"); @@ -339,13 +350,13 @@ void MohawkEngine_Riven::refreshCard() { } void MohawkEngine_Riven::loadCard(uint16 id) { - // NOTE: Do not clear the card scripts because it may delete a currently running script! + // NOTE: The card scripts are cleared by the RivenScriptManager automatically. Common::SeekableReadStream* inStream = getRawData(ID_CARD, id); _cardData.name = inStream->readSint16BE(); _cardData.zipModePlace = inStream->readUint16BE(); - _cardData.scripts = RivenScript::readScripts(this, inStream); + _cardData.scripts = _scriptMan->readScripts(inStream); _cardData.hasData = true; delete inStream; @@ -363,7 +374,10 @@ void MohawkEngine_Riven::loadCard(uint16 id) { } void MohawkEngine_Riven::loadHotspots(uint16 id) { - // NOTE: Do not clear the hotspots because it may delete a currently running script! + // Clear old hotspots + delete[] _hotspots; + + // NOTE: The hotspot scripts are cleared by the RivenScriptManager automatically. Common::SeekableReadStream* inStream = getRawData(ID_HSPT, id); @@ -405,7 +419,7 @@ void MohawkEngine_Riven::loadHotspots(uint16 id) { _hotspots[i].zipModeHotspot = inStream->readUint16BE(); // Read in the scripts now - _hotspots[i].scripts = RivenScript::readScripts(this, inStream); + _hotspots[i].scripts = _scriptMan->readScripts(inStream); } delete inStream; @@ -480,26 +494,37 @@ void MohawkEngine_Riven::checkInventoryClick() { *matchVarToString("returncardid") = _curCard; // See RivenGraphics::showInventory() for an explanation - // of why only this variable is used. + // of the variables' meanings. bool hasCathBook = *matchVarToString("acathbook") != 0; + bool hasTrapBook = *matchVarToString("atrapbook") != 0; // Go to the book if a hotspot contains the mouse if (!hasCathBook) { - if (g_atrusJournalRectSolo->contains(_mousePos)) { + if (g_atrusJournalRect1->contains(_mousePos)) { _gfx->hideInventory(); changeToStack(aspit); changeToCard(5); } + } else if (!hasTrapBook) { + if (g_atrusJournalRect2->contains(_mousePos)) { + _gfx->hideInventory(); + changeToStack(aspit); + changeToCard(5); + } else if (g_cathJournalRect2->contains(_mousePos)) { + _gfx->hideInventory(); + changeToStack(aspit); + changeToCard(6); + } } else { - if (g_atrusJournalRect->contains(_mousePos)) { + if (g_atrusJournalRect3->contains(_mousePos)) { _gfx->hideInventory(); changeToStack(aspit); changeToCard(5); - } else if (g_cathJournalRect->contains(_mousePos)) { + } else if (g_cathJournalRect3->contains(_mousePos)) { _gfx->hideInventory(); changeToStack(aspit); changeToCard(6); - } else if (g_trapBookRect->contains(_mousePos)) { + } else if (g_trapBookRect3->contains(_mousePos)) { _gfx->hideInventory(); changeToStack(aspit); changeToCard(7); @@ -583,7 +608,19 @@ void MohawkEngine_Riven::runHotspotScript(uint16 hotspot, uint16 scriptType) { } void MohawkEngine_Riven::runLoadDialog() { - runDialog(*_loadDialog); + GUI::SaveLoadChooser slc("Load Game:", "Load"); + slc.setSaveMode(false); + + Common::String gameId = ConfMan.get("gameid"); + + const EnginePlugin *plugin = 0; + EngineMan.findGame(gameId, &plugin); + + int slot = slc.runModal(plugin, ConfMan.getActiveDomainName()); + if (slot >= 0) + loadGameState(slot); + + slc.close(); } Common::Error MohawkEngine_Riven::loadGameState(int slot) { @@ -618,4 +655,4 @@ bool ZipMode::operator== (const ZipMode &z) const { return z.name == name && z.id == id; } -} +} // End of namespace Mohawk diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h index 11c3a4c0cb..631285455e 100644 --- a/engines/mohawk/riven.h +++ b/engines/mohawk/riven.h @@ -68,10 +68,12 @@ enum { // Rects for the inventory object positions (initialized in // MohawkEngine_Riven's constructor). -extern Common::Rect *g_atrusJournalRectSolo; -extern Common::Rect *g_atrusJournalRect; -extern Common::Rect *g_cathJournalRect; -extern Common::Rect *g_trapBookRect; +extern Common::Rect *g_atrusJournalRect1; +extern Common::Rect *g_atrusJournalRect2; +extern Common::Rect *g_cathJournalRect2; +extern Common::Rect *g_atrusJournalRect3; +extern Common::Rect *g_cathJournalRect3; +extern Common::Rect *g_trapBookRect3; struct RivenHotspot { uint16 blstID; @@ -111,6 +113,7 @@ public: RivenGraphics *_gfx; RivenExternal *_externalScriptHandler; Common::RandomSource *_rnd; + RivenScriptManager *_scriptMan; Card _cardData; @@ -126,7 +129,6 @@ private: MohawkArchive *_extrasFile; // We need a separate handle for the extra data RivenConsole *_console; RivenSaveLoad *_saveLoad; - GUI::SaveLoadChooser *_loadDialog; RivenOptionsDialog *_optionsDialog; // Stack/Card-related functions and variables diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index 4e6bba1c2a..67d621a54c 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -284,9 +284,14 @@ void RivenExternal::xaatrusbookprevpage(uint16 argc, uint16 *argv) { return; (*page)--; - // TODO: Play the page turning sound + // Play the page turning sound + if (_vm->getFeatures() & GF_DEMO) + _vm->_sound->playSound(4, false); + else + _vm->_sound->playSound(3, false); // Now update the screen :) + _vm->_gfx->scheduleTransition(1); _vm->_gfx->updateScreen(); } @@ -299,9 +304,14 @@ void RivenExternal::xaatrusbooknextpage(uint16 argc, uint16 *argv) { return; (*page)++; - // TODO: Play the page turning sound + // Play the page turning sound + if (_vm->getFeatures() & GF_DEMO) + _vm->_sound->playSound(5, false); + else + _vm->_sound->playSound(4, false); // Now update the screen :) + _vm->_gfx->scheduleTransition(0); _vm->_gfx->updateScreen(); } @@ -349,9 +359,11 @@ void RivenExternal::xacathbookprevpage(uint16 argc, uint16 *argv) { return; (*page)--; - // TODO: Play the page turning sound + // Play the page turning sound + _vm->_sound->playSound(5, false); // Now update the screen :) + _vm->_gfx->scheduleTransition(3); _vm->_gfx->updateScreen(); } @@ -364,9 +376,11 @@ void RivenExternal::xacathbooknextpage(uint16 argc, uint16 *argv) { return; (*page)++; - // TODO: Play the page turning sound + // Play the page turning sound + _vm->_sound->playSound(6, false); // Now update the screen :) + _vm->_gfx->scheduleTransition(2); _vm->_gfx->updateScreen(); } @@ -380,12 +394,20 @@ void RivenExternal::xtrapbookback(uint16 argc, uint16 *argv) { void RivenExternal::xatrapbookclose(uint16 argc, uint16 *argv) { // Close the trap book *_vm->matchVarToString("atrap") = 0; + + // Play the page turning sound + _vm->_sound->playSound(8, false); + _vm->refreshCard(); } void RivenExternal::xatrapbookopen(uint16 argc, uint16 *argv) { // Open the trap book *_vm->matchVarToString("atrap") = 1; + + // Play the page turning sound + _vm->_sound->playSound(9, false); + _vm->refreshCard(); } @@ -437,7 +459,11 @@ void RivenExternal::xblabbookprevpage(uint16 argc, uint16 *argv) { return; (*page)--; + // Play the page turning sound + _vm->_sound->playSound(22, false); + // Now update the screen :) + _vm->_gfx->scheduleTransition(1); _vm->_gfx->updateScreen(); } @@ -450,7 +476,11 @@ void RivenExternal::xblabbooknextpage(uint16 argc, uint16 *argv) { return; (*page)++; + // Play the page turning sound + _vm->_sound->playSound(23, false); + // Now update the screen :) + _vm->_gfx->scheduleTransition(0); _vm->_gfx->updateScreen(); } @@ -662,15 +692,17 @@ void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) { // Get the variable for the valve uint32 *valve = _vm->matchVarToString("bvalve"); - Common::Event event; int changeX = 0; int changeY = 0; + bool done = false; // Set the cursor to the closed position _vm->_gfx->changeCursor(2004); _vm->_system->updateScreen(); - for (;;) { + while (!done) { + Common::Event event; + while (_vm->_system->getEventManager()->pollEvent(event)) { switch (event.type) { case Common::EVENT_MOUSEMOVE: @@ -682,30 +714,53 @@ void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) { // FIXME: These values for changes in x/y could be tweaked. if (*valve == 0 && changeY <= -10) { *valve = 1; - // TODO: Play movie + _vm->_gfx->changeCursor(kRivenHideCursor); + _vm->_video->playMovieBlocking(2); _vm->refreshCard(); } else if (*valve == 1) { if (changeX >= 0 && changeY >= 10) { *valve = 0; - // TODO: Play movie + _vm->_gfx->changeCursor(kRivenHideCursor); + _vm->_video->playMovieBlocking(3); _vm->refreshCard(); } else if (changeX <= -10 && changeY <= 10) { *valve = 2; - // TODO: Play movie + _vm->_gfx->changeCursor(kRivenHideCursor); + _vm->_video->playMovieBlocking(1); _vm->refreshCard(); } } else if (*valve == 2 && changeX >= 10) { *valve = 1; - // TODO: Play movie + _vm->_gfx->changeCursor(kRivenHideCursor); + _vm->_video->playMovieBlocking(4); _vm->refreshCard(); } - return; + done = true; default: break; } } _vm->_system->delayMillis(10); } + + // If we changed state and the new state is that the valve is flowing to + // the boiler, we need to update the boiler state. + if (*valve == 1) { + if (*_vm->matchVarToString("bidvlv") == 1) { // Check which way the water is going at the boiler + if (*_vm->matchVarToString("bblrarm") == 1) { + // If the pipe is open, make sure the water is drained out + *_vm->matchVarToString("bheat") = 0; + *_vm->matchVarToString("bblrwtr") = 0; + } else { + // If the pipe is closed, fill the boiler again + *_vm->matchVarToString("bheat") = *_vm->matchVarToString("bblrvalve"); + *_vm->matchVarToString("bblrwtr") = 1; + } + } else { + // Have the grating inside the boiler match the switch outside + *_vm->matchVarToString("bblrgrt") = (*_vm->matchVarToString("bblrsw") == 1) ? 0 : 1; + } + } } void RivenExternal::xbchipper(uint16 argc, uint16 *argv) { @@ -960,33 +1015,60 @@ void RivenExternal::xjtunnel106_pictfix(uint16 argc, uint16 *argv) { } void RivenExternal::xvga1300_carriage(uint16 argc, uint16 *argv) { - // TODO: This function is supposed to do a lot more, something like this (pseudocode): - - // Show level pull movie - // Set transition up - // Change to up card - // Show movie of carriage coming down - // Set transition down - // Change back to card 276 - // Show movie of carriage coming down - // if jgallows == 0 - // Set up timer - // Enter new input loop - // if you click within the time - // move forward - // set transition right - // change to card right - // show movie of ascending - // change to card 263 - // else - // show movie of carriage ascending only - // else - // show movie of carriage ascending only - - - // For now, if the gallows base is closed, assume ascension and move to that card. - if (*_vm->matchVarToString("jgallows") == 0) - _vm->changeToCard(_vm->matchRMAPToCard(0x17167)); + // Run the gallows's carriage + + _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor + _vm->_video->playMovieBlocking(1); // Play handle movie + _vm->_gfx->scheduleTransition(15); // Set pan down transition + _vm->changeToCard(_vm->matchRMAPToCard(0x18e77)); // Change to card facing up + _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor (again) + _vm->_video->playMovieBlocking(4); // Play carriage beginning to drop + _vm->_gfx->scheduleTransition(14); // Set pan up transition + _vm->changeToCard(_vm->matchRMAPToCard(0x183a9)); // Change to card looking straight again + _vm->_video->playMovieBlocking(2); + + uint32 *gallows = _vm->matchVarToString("jgallows"); + if (*gallows == 1) { + // If the gallows is open, play the up movie and return + _vm->_video->playMovieBlocking(3); + return; + } + + // Give the player 5 seconds to click (anywhere) + uint32 startTime = _vm->_system->getMillis(); + bool gotClick = false; + while (_vm->_system->getMillis() - startTime <= 5000 && !gotClick) { + Common::Event event; + while (_vm->_system->getEventManager()->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_MOUSEMOVE: + _vm->_system->updateScreen(); + break; + case Common::EVENT_LBUTTONUP: + gotClick = true; + break; + default: + break; + } + } + + _vm->_system->delayMillis(10); + } + + _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor + + if (gotClick) { + _vm->_gfx->scheduleTransition(16); // Schedule dissolve transition + _vm->changeToCard(_vm->matchRMAPToCard(0x18d4d)); // Move forward + _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor + _vm->_system->delayMillis(500); // Delay a half second before changing again + _vm->_gfx->scheduleTransition(12); // Schedule pan left transition + _vm->changeToCard(_vm->matchRMAPToCard(0x18ab5)); // Turn right + _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor + _vm->_video->playMovieBlocking(1); // Play carriage ride movie + _vm->changeToCard(_vm->matchRMAPToCard(0x17167)); // We have arrived at the top + } else + _vm->_video->playMovieBlocking(3); // Too slow! } void RivenExternal::xjdome25_resetsliders(uint16 argc, uint16 *argv) { @@ -1043,8 +1125,10 @@ int RivenExternal::jspitElevatorLoop() { void RivenExternal::xhandlecontrolup(uint16 argc, uint16 *argv) { int changeLevel = jspitElevatorLoop(); + // If we've moved the handle down, go down a floor if (changeLevel == -1) { - // TODO: Run movie + _vm->_video->playMovieBlocking(1); + _vm->_video->playMovieBlocking(2); _vm->changeToCard(_vm->matchRMAPToCard(0x1e374)); } } @@ -1052,8 +1136,10 @@ void RivenExternal::xhandlecontrolup(uint16 argc, uint16 *argv) { void RivenExternal::xhandlecontroldown(uint16 argc, uint16 *argv) { int changeLevel = jspitElevatorLoop(); + // If we've moved the handle up, go up a floor if (changeLevel == 1) { - // TODO: Run movie + _vm->_video->playMovieBlocking(1); + _vm->_video->playMovieBlocking(2); _vm->changeToCard(_vm->matchRMAPToCard(0x1e374)); } } @@ -1061,11 +1147,29 @@ void RivenExternal::xhandlecontroldown(uint16 argc, uint16 *argv) { void RivenExternal::xhandlecontrolmid(uint16 argc, uint16 *argv) { int changeLevel = jspitElevatorLoop(); + if (changeLevel == 0) + return; + + // Play the handle moving video + if (changeLevel == 1) + _vm->_video->playMovieBlocking(7); + else + _vm->_video->playMovieBlocking(6); + + // If the whark's mouth is open, close it + uint32 *mouthVar = _vm->matchVarToString("jwmouth"); + if (*mouthVar == 1) { + _vm->_video->playMovieBlocking(3); + _vm->_video->playMovieBlocking(8); + *mouthVar = 0; + } + + // Play the elevator video and then change the card if (changeLevel == 1) { - // TODO: Run movie + _vm->_video->playMovieBlocking(5); _vm->changeToCard(_vm->matchRMAPToCard(0x1e597)); - } else if (changeLevel == -1) { - // TODO: Run movie + } else { + _vm->_video->playMovieBlocking(4); _vm->changeToCard(_vm->matchRMAPToCard(0x1e29c)); } } @@ -1196,9 +1300,11 @@ void RivenExternal::xogehnbookprevpage(uint16 argc, uint16 *argv) { return; (*page)--; - // TODO: Play the page turning sound + // Play the page turning sound + _vm->_sound->playSound(12, false); // Now update the screen :) + _vm->_gfx->scheduleTransition(1); _vm->_gfx->updateScreen(); } @@ -1211,13 +1317,15 @@ void RivenExternal::xogehnbooknextpage(uint16 argc, uint16 *argv) { return; (*page)++; - // TODO: Play the page turning sound + // Play the page turning sound + _vm->_sound->playSound(13, false); // Now update the screen :) + _vm->_gfx->scheduleTransition(0); _vm->_gfx->updateScreen(); } -static uint16 getComboDigit(uint32 correctCombo, uint32 digit) { +uint16 RivenExternal::getComboDigit(uint32 correctCombo, uint32 digit) { static const uint32 powers[] = { 100000, 10000, 1000, 100, 10, 1 }; return (correctCombo % powers[digit]) / powers[digit + 1]; } diff --git a/engines/mohawk/riven_external.h b/engines/mohawk/riven_external.h index 14bb51340c..bdf3fa01bc 100644 --- a/engines/mohawk/riven_external.h +++ b/engines/mohawk/riven_external.h @@ -38,6 +38,7 @@ public: ~RivenExternal(); void runCommand(uint16 argc, uint16 *argv); + uint16 getComboDigit(uint32 correctCombo, uint32 digit); private: MohawkEngine_Riven *_vm; diff --git a/engines/mohawk/riven_saveload.cpp b/engines/mohawk/riven_saveload.cpp index 3c989838da..d73b4ec0dc 100644 --- a/engines/mohawk/riven_saveload.cpp +++ b/engines/mohawk/riven_saveload.cpp @@ -23,6 +23,7 @@ * */ +#include "mohawk/resource.h" #include "mohawk/riven.h" #include "mohawk/riven_saveload.h" @@ -31,11 +32,9 @@ namespace Mohawk { RivenSaveLoad::RivenSaveLoad(MohawkEngine_Riven *vm, Common::SaveFileManager *saveFileMan) : _vm(vm), _saveFileMan(saveFileMan) { - _loadFile = new MohawkArchive(); } RivenSaveLoad::~RivenSaveLoad() { - delete _loadFile; } Common::StringArray RivenSaveLoad::generateSaveGameList() { @@ -63,7 +62,8 @@ static uint16 mapOldStackIDToNew(uint16 oldID) { case 8: return aspit; } - error ("Unknown old stack ID %d", oldID); + + error("Unknown old stack ID %d", oldID); return 0; } @@ -86,7 +86,8 @@ static uint16 mapNewStackIDToOld(uint16 newID) { case tspit: return 4; } - error ("Unknown new stack ID %d", newID); + + error("Unknown new stack ID %d", newID); return 0; } @@ -94,26 +95,28 @@ bool RivenSaveLoad::loadGame(Common::String filename) { if (_vm->getFeatures() & GF_DEMO) // Don't load games in the demo return false; - Common::InSaveFile *loadFile; - if (!(loadFile = _saveFileMan->openForLoading(filename.c_str()))) + Common::InSaveFile *loadFile = _saveFileMan->openForLoading(filename); + if (!loadFile) return false; - debug (0, "Loading game from \'%s\'", filename.c_str()); - _loadFile->open(loadFile); + debug(0, "Loading game from \'%s\'", filename.c_str()); + + MohawkArchive *mhk = new MohawkArchive(); + mhk->open(loadFile); // First, let's make sure we're using a saved game file from this version of Riven by checking the VERS resource - Common::SeekableReadStream *vers = _loadFile->getRawData(ID_VERS, 1); + Common::SeekableReadStream *vers = mhk->getRawData(ID_VERS, 1); uint32 saveGameVersion = vers->readUint32BE(); delete vers; if ((saveGameVersion == kCDSaveGameVersion && (_vm->getFeatures() & GF_DVD)) || (saveGameVersion == kDVDSaveGameVersion && !(_vm->getFeatures() & GF_DVD))) { - warning ("Incompatible saved game versions. No support for this yet."); - delete _loadFile; + warning("Incompatible saved game versions. No support for this yet."); + delete mhk; return false; } // Now, we'll read in the variable values. - Common::SeekableReadStream *vars = _loadFile->getRawData(ID_VARS, 1); + Common::SeekableReadStream *vars = mhk->getRawData(ID_VARS, 1); Common::Array<uint32> rawVariables; while (!vars->eos()) { @@ -126,7 +129,7 @@ bool RivenSaveLoad::loadGame(Common::String filename) { // Next, we set the variables based on the name found by the index in the VARS resource. // TODO: Merge with code in mohawk.cpp for loading names? - Common::SeekableReadStream *names = _loadFile->getRawData(ID_NAME, 1); + Common::SeekableReadStream *names = mhk->getRawData(ID_NAME, 1); uint16 namesCount = names->readUint16BE(); uint16 *stringOffsets = new uint16[namesCount]; @@ -151,9 +154,10 @@ bool RivenSaveLoad::loadGame(Common::String filename) { c = (char)names->readByte(); } - // WORKAROUND: Some versions have two extra variables. However, the saves are - // still compatible with other saves of the same version. Are these used in the - // original interpreter anywhere? (They come from DVD v1.1) + // TODO: Some versions have two extra variables. However, the saves are + // still compatible with other saves of the same version (they come from DVD v1.1). + // There are used in the whark number puzzle. I thought jleftpos and jrightpos were + // for this purpose. if (name == "dropLeftStart" || name == "dropRightStart") continue; @@ -161,11 +165,11 @@ bool RivenSaveLoad::loadGame(Common::String filename) { *var = rawVariables[i]; - if (!scumm_stricmp(name.c_str(), "CurrentStackID")) + if (name.equalsIgnoreCase("CurrentStackID")) stackID = mapOldStackIDToNew(rawVariables[i]); - else if (!scumm_stricmp(name.c_str(), "CurrentCardID")) + else if (name.equalsIgnoreCase("CurrentCardID")) cardID = rawVariables[i]; - else if (!scumm_stricmp(name.c_str(), "ReturnStackID")) + else if (name.equalsIgnoreCase("ReturnStackID")) *var = mapOldStackIDToNew(rawVariables[i]); } @@ -179,7 +183,7 @@ bool RivenSaveLoad::loadGame(Common::String filename) { _vm->_zipModeData.clear(); // Finally, we load in zip mode data. - Common::SeekableReadStream *zips = _loadFile->getRawData(ID_ZIPS, 1); + Common::SeekableReadStream *zips = mhk->getRawData(ID_ZIPS, 1); uint16 zipsRecordCount = zips->readUint16BE(); for (uint16 i = 0; i < zipsRecordCount; i++) { ZipMode zip; @@ -189,10 +193,10 @@ bool RivenSaveLoad::loadGame(Common::String filename) { zip.id = zips->readUint16BE(); _vm->_zipModeData.push_back(zip); } + delete zips; + delete mhk; - delete _loadFile; - _loadFile = NULL; return true; } @@ -211,7 +215,14 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genVARSSection() { for (uint32 i = 0; i < _vm->getVarCount(); i++) { stream->writeUint32BE(0); // Unknown stream->writeUint32BE(0); // Unknown - stream->writeUint32BE(_vm->getGlobalVar(i)); + + // Remap returnstackid here because we don't actually want to change + // our internal returnstackid. + uint32 variable = _vm->getGlobalVar(i); + if (_vm->getGlobalVarName(i) == "returnstackid") + variable = mapNewStackIDToOld(variable); + + stream->writeUint32BE(variable); } return stream; @@ -257,17 +268,17 @@ bool RivenSaveLoad::saveGame(Common::String filename) { // Note, this code is still WIP. It works quite well for now. // Make sure we have the right extension - if (!filename.hasSuffix(".rvn") && !filename.hasSuffix(".RVN")) + if (!filename.matchString("*.rvn", true)) filename += ".rvn"; // Convert class variables to variable numbers *_vm->matchVarToString("currentstackid") = mapNewStackIDToOld(_vm->getCurStack()); *_vm->matchVarToString("currentcardid") = _vm->getCurCard(); - *_vm->matchVarToString("returnstackid") = mapNewStackIDToOld(*_vm->matchVarToString("returnstackid")); - Common::OutSaveFile *saveFile; - if (!(saveFile = _saveFileMan->openForSaving(filename.c_str()))) + Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(filename); + if (!saveFile) return false; + debug (0, "Saving game to \'%s\'", filename.c_str()); Common::MemoryWriteStreamDynamic *versSection = genVERSSection(); @@ -392,7 +403,7 @@ bool RivenSaveLoad::saveGame(Common::String filename) { void RivenSaveLoad::deleteSave(Common::String saveName) { debug (0, "Deleting save file \'%s\'", saveName.c_str()); - _saveFileMan->removeSavefile(saveName.c_str()); + _saveFileMan->removeSavefile(saveName); } } // End of namespace Mohawk diff --git a/engines/mohawk/riven_saveload.h b/engines/mohawk/riven_saveload.h index c708f9d35d..9cc9bc3737 100644 --- a/engines/mohawk/riven_saveload.h +++ b/engines/mohawk/riven_saveload.h @@ -29,8 +29,6 @@ #include "common/savefile.h" #include "common/str.h" -#include "mohawk/resource.h" - namespace Mohawk { class MohawkEngine_Riven; @@ -53,7 +51,6 @@ public: private: MohawkEngine_Riven *_vm; Common::SaveFileManager *_saveFileMan; - MohawkArchive *_loadFile; Common::MemoryWriteStreamDynamic *genVERSSection(); Common::MemoryWriteStreamDynamic *genNAMESection(); diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp index d574a455c6..1fcaba8ac0 100644 --- a/engines/mohawk/riven_scripts.cpp +++ b/engines/mohawk/riven_scripts.cpp @@ -35,33 +35,21 @@ namespace Mohawk { -RivenScript::RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType) - : _vm(vm), _stream(stream), _scriptType(scriptType) { +RivenScript::RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType, uint16 parentStack, uint16 parentCard) + : _vm(vm), _stream(stream), _scriptType(scriptType), _parentStack(parentStack), _parentCard(parentCard) { setupOpcodes(); + _isRunning = false; } RivenScript::~RivenScript() { delete _stream; } -RivenScriptList RivenScript::readScripts(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream) { - RivenScriptList scriptList; - - uint16 scriptCount = stream->readUint16BE(); - for (uint16 i = 0; i < scriptCount; i++) { - uint16 scriptType = stream->readUint16BE(); - uint32 scriptSize = calculateScriptSize(stream); - scriptList.push_back(Common::SharedPtr<RivenScript>(new RivenScript(vm, stream->readStream(scriptSize), scriptType))); - } - - return scriptList; -} - uint32 RivenScript::calculateCommandSize(Common::SeekableReadStream* script) { uint16 command = script->readUint16BE(); uint32 commandSize = 2; if (command == 8) { - if (script->readUint16BE() != 2) + if (script->readUint16BE() != 2) // Arg count? warning ("if-then-else unknown value is not 2"); script->readUint16BE(); // variable to check against uint16 logicBlockCount = script->readUint16BE(); // number of logic blocks @@ -161,7 +149,7 @@ void RivenScript::setupOpcodes() { OPCODE(activateFLST), OPCODE(zipMode), OPCODE(activateMLST), - OPCODE(activateSLSTWithVolume) + OPCODE(empty) // Activate an SLST with a volume parameter (not used) }; _opcodes = riven_opcodes; @@ -239,10 +227,13 @@ void RivenScript::dumpCommands(Common::StringArray varNames, Common::StringArray } void RivenScript::runScript() { + _isRunning = true; + if (_stream->pos() != 0) _stream->seek(0); processCommands(true); + _isRunning = false; } void RivenScript::processCommands(bool runCommands) { @@ -610,9 +601,46 @@ void RivenScript::activateMLST(uint16 op, uint16 argc, uint16 *argv) { _vm->_video->activateMLST(argv[0], _vm->getCurCard()); } -// Command 47: activate SLST record with a volume argument -void RivenScript::activateSLSTWithVolume(uint16 op, uint16 argc, uint16 *argv) { - warning("STUB: activateSLSTWithVolume()"); +RivenScriptManager::RivenScriptManager(MohawkEngine_Riven *vm) { + _vm = vm; +} + +RivenScriptManager::~RivenScriptManager() { + for (uint32 i = 0; i < _currentScripts.size(); i++) + delete _currentScripts[i]; +} + +RivenScriptList RivenScriptManager::readScripts(Common::SeekableReadStream *stream, bool garbageCollect) { + if (garbageCollect) + unloadUnusedScripts(); // Garbage collect! + + RivenScriptList scriptList; + + uint16 scriptCount = stream->readUint16BE(); + for (uint16 i = 0; i < scriptCount; i++) { + uint16 scriptType = stream->readUint16BE(); + uint32 scriptSize = RivenScript::calculateScriptSize(stream); + RivenScript *script = new RivenScript(_vm, stream->readStream(scriptSize), scriptType, _vm->getCurStack(), _vm->getCurCard()); + scriptList.push_back(script); + + // Only add it to the scripts that we will free later if it is requested. + // (ie. we don't want to store scripts from the dumpScript console command) + if (garbageCollect) + _currentScripts.push_back(script); + } + + return scriptList; +} + +void RivenScriptManager::unloadUnusedScripts() { + // Free any scripts that aren't part of the current card and aren't running + for (uint32 i = 0; i < _currentScripts.size(); i++) { + if ((_vm->getCurStack() != _currentScripts[i]->getParentStack() || _vm->getCurCard() != _currentScripts[i]->getParentCard()) && !_currentScripts[i]->isRunning()) { + delete _currentScripts[i]; + _currentScripts.remove_at(i); + i--; + } + } } } // End of namespace Mohawk diff --git a/engines/mohawk/riven_scripts.h b/engines/mohawk/riven_scripts.h index a1512af697..5187bbde08 100644 --- a/engines/mohawk/riven_scripts.h +++ b/engines/mohawk/riven_scripts.h @@ -50,19 +50,20 @@ enum { }; class RivenScript; -typedef Common::Array<Common::SharedPtr<RivenScript> > RivenScriptList; class RivenScript { public: - RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType); + RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType, uint16 parentStack, uint16 parentCard); ~RivenScript(); void runScript(); void dumpScript(Common::StringArray varNames, Common::StringArray xNames, byte tabs); uint16 getScriptType() { return _scriptType; } + uint16 getParentStack() { return _parentStack; } + uint16 getParentCard() { return _parentCard; } + bool isRunning() { return _isRunning; } - // Read in an array of script objects from a stream - static RivenScriptList readScripts(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream); + static uint32 calculateScriptSize(Common::SeekableReadStream *script); private: typedef void (RivenScript::*OpcodeProcRiven)(uint16 op, uint16 argc, uint16 *argv); @@ -70,18 +71,18 @@ private: OpcodeProcRiven proc; const char *desc; }; - const RivenOpcode* _opcodes; + const RivenOpcode *_opcodes; void setupOpcodes(); MohawkEngine_Riven *_vm; Common::SeekableReadStream *_stream; - uint16 _scriptType; + uint16 _scriptType, _parentStack, _parentCard, _parentHotspot; + bool _isRunning; void dumpCommands(Common::StringArray varNames, Common::StringArray xNames, byte tabs); void processCommands(bool runCommands); - static uint32 calculateCommandSize(Common::SeekableReadStream* script); - static uint32 calculateScriptSize(Common::SeekableReadStream* script); + static uint32 calculateCommandSize(Common::SeekableReadStream *script); DECLARE_OPCODE(empty) { warning ("Unknown Opcode %04x", op); } @@ -120,7 +121,21 @@ private: DECLARE_OPCODE(activateFLST); DECLARE_OPCODE(zipMode); DECLARE_OPCODE(activateMLST); - DECLARE_OPCODE(activateSLSTWithVolume); +}; + +typedef Common::Array<RivenScript*> RivenScriptList; + +class RivenScriptManager { +public: + RivenScriptManager(MohawkEngine_Riven *vm); + ~RivenScriptManager(); + + RivenScriptList readScripts(Common::SeekableReadStream *stream, bool garbageCollect = true); + +private: + void unloadUnusedScripts(); + RivenScriptList _currentScripts; + MohawkEngine_Riven *_vm; }; } // End of namespace Mohawk diff --git a/engines/mohawk/riven_vars.cpp b/engines/mohawk/riven_vars.cpp index 3f7cd5a8b6..b6d2dff315 100644 --- a/engines/mohawk/riven_vars.cpp +++ b/engines/mohawk/riven_vars.cpp @@ -319,6 +319,8 @@ void MohawkEngine_Riven::initVars() { *matchVarToString("bheat") = 1; *matchVarToString("waterenabled") = 1; *matchVarToString("ogehnpage") = 1; + *matchVarToString("bblrsw") = 1; + *matchVarToString("ocage") = 1; // Randomize the telescope combination uint32 *teleCombo = matchVarToString("tcorrectorder"); diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp index b84573f011..091bd68021 100644 --- a/engines/mohawk/sound.cpp +++ b/engines/mohawk/sound.cpp @@ -27,12 +27,12 @@ #include "common/util.h" +#include "sound/musicplugin.h" #include "sound/audiostream.h" #include "sound/decoders/mp3.h" #include "sound/decoders/raw.h" #include "sound/decoders/wave.h" - namespace Mohawk { Sound::Sound(MohawkEngine* vm) : _vm(vm) { @@ -79,7 +79,7 @@ void Sound::initMidi() { // Let's get our MIDI parser/driver _midiParser = MidiParser::createParser_SMF(); - _midiDriver = MidiDriver::createMidi(MidiDriver::detectMusicDriver(MDT_ADLIB|MDT_MIDI)); + _midiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(MDT_ADLIB|MDT_MIDI)); // Set up everything! _midiDriver->open(); @@ -233,6 +233,10 @@ void Sound::playSLST(uint16 index, uint16 card) { if (slstRecord.index == index) { playSLST(slstRecord); + delete[] slstRecord.sound_ids; + delete[] slstRecord.volumes; + delete[] slstRecord.balances; + delete[] slstRecord.u2; delete slstStream; return; } @@ -244,6 +248,7 @@ void Sound::playSLST(uint16 index, uint16 card) { } delete slstStream; + // No matching records, assume we need to stop all SLST's stopAllSLST(); } @@ -277,8 +282,11 @@ void Sound::playSLST(SLSTRecord slstRecord) { } void Sound::stopAllSLST() { - for (uint16 i = 0; i < _currentSLSTSounds.size(); i++) + for (uint16 i = 0; i < _currentSLSTSounds.size(); i++) { _vm->_mixer->stopHandle(*_currentSLSTSounds[i].handle); + delete _currentSLSTSounds[i].handle; + } + _currentSLSTSounds.clear(); } @@ -314,6 +322,7 @@ void Sound::playSLSTSound(uint16 id, bool fade, bool loop, uint16 volume, int16 void Sound::stopSLSTSound(uint16 index, bool fade) { // TODO: Fade out, mixer needs to be extended to get volume on a handle _vm->_mixer->stopHandle(*_currentSLSTSounds[index].handle); + delete _currentSLSTSounds[index].handle; _currentSLSTSounds.remove_at(index); } diff --git a/engines/parallaction/callables_ns.cpp b/engines/parallaction/callables_ns.cpp index a493523301..cfe6ad8954 100644 --- a/engines/parallaction/callables_ns.cpp +++ b/engines/parallaction/callables_ns.cpp @@ -453,14 +453,15 @@ void Parallaction_ns::_c_startIntro(void *parm) { } void Parallaction_ns::_c_endIntro(void *parm) { - // NOTE: suspend command execution queue, to - // avoid running the QUIT command before - // credits are displayed. This solves bug - // #2619824. - // Execution of the command list will resume - // as soon as runGameFrame is run. - _cmdExec->suspend(); - + if (getFeatures() & GF_DEMO) { + // NOTE: suspend command execution queue, to + // avoid running the QUIT command before + // credits are displayed. This solves bug + // #2619824. + // Execution of the command list will resume + // as soon as runGameFrame is run. + _cmdExec->suspend(); + } startCreditSequence(); _intro = false; } diff --git a/engines/parallaction/detection.cpp b/engines/parallaction/detection.cpp index e5e2b22644..e00a087923 100644 --- a/engines/parallaction/detection.cpp +++ b/engines/parallaction/detection.cpp @@ -240,7 +240,11 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NOLAUNCHLOAD + Common::GUIO_NOLAUNCHLOAD, + // Maximum directory depth + 1, + // List of directory globs + 0 }; class ParallactionMetaEngine : public AdvancedMetaEngine { diff --git a/engines/parallaction/exec.cpp b/engines/parallaction/exec.cpp index 24579286e6..434c4f6ae6 100644 --- a/engines/parallaction/exec.cpp +++ b/engines/parallaction/exec.cpp @@ -193,8 +193,10 @@ void CommandExec::runSuspended() { debugC(3, kDebugExec, "CommandExec::runSuspended()"); _execZone = _suspendedCtxt._zone; - runList(_suspendedCtxt._first, _suspendedCtxt._last); + CommandList::iterator first = _suspendedCtxt._first; + CommandList::iterator last = _suspendedCtxt._last; cleanSuspendedList(); + runList(first, last); } } diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp index e145c0da94..1d8724e2d8 100644 --- a/engines/parallaction/exec_br.cpp +++ b/engines/parallaction/exec_br.cpp @@ -293,7 +293,7 @@ DECLARE_COMMAND_OPCODE(text) { DECLARE_COMMAND_OPCODE(part) { - warning("Parallaction_br::cmdOp_part not yet implemented"); + _vm->_nextPart = ctxt._cmd->_counterValue; } @@ -527,6 +527,11 @@ DECLARE_INSTRUCTION_OPCODE(endif) { DECLARE_INSTRUCTION_OPCODE(stop) { ZonePtr z = ctxt._inst->_z; + + // Prevent execution if zone is missing. The known case is "PART2/insegui.scr", which has + // "STOP insegui", which doesn't exist (see ticket #3021744 for the gory details) + if (!z) return; + if (ACTIONTYPE(z) == kZoneHear) { warning("Parallaction_br::instOp_stop not yet implemented for HEAR zones"); // TODO: stop music or sound effects generated by a zone. diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp index fc6cb28d9e..a1926fc197 100644 --- a/engines/parallaction/gfxbase.cpp +++ b/engines/parallaction/gfxbase.cpp @@ -222,10 +222,12 @@ void Gfx::drawGfxObject(GfxObj *obj, Graphics::Surface &surf) { obj->getRect(obj->frame, rect); int x = obj->x; + int y = obj->y; if (_overlayMode) { x += _scrollPosX; + y += _scrollPosY; } - rect.translate(x, obj->y); + rect.translate(x, y); data = obj->getData(obj->frame); if (obj->getSize(obj->frame) == obj->getRawSize(obj->frame)) { @@ -281,30 +283,54 @@ void Gfx::bltMaskScale(const Common::Rect& r, byte *data, Graphics::Surface *sur return; } - Common::Rect q(r); - Common::Rect clipper(surf->w, surf->h); - q.clip(clipper); - if (!q.isValidRect()) return; - - uint inc = r.width() * (100 - scale); - uint thr = r.width() * 100; - uint xAccum = 0, yAccum = 0; + // unscaled rectangle size + uint width = r.width(); + uint height = r.height(); + + // scaled rectangle size + uint scaledWidth = r.width() * scale / 100; + uint scaledHeight = r.height() * scale / 100; + + // scaled rectangle origin + uint scaledLeft = r.left + (width - scaledWidth) / 2; + uint scaledTop = r.top + (height - scaledHeight); + + // clipped scaled destination rectangle + Common::Rect dstRect(scaledWidth, scaledHeight); + dstRect.moveTo(scaledLeft, scaledTop); + + Common::Rect clipper(surf->w, surf->h); + dstRect.clip(clipper); + if (!dstRect.isValidRect()) return; + + + // clipped source rectangle + Common::Rect srcRect; + srcRect.left = (dstRect.left - scaledLeft) * 100 / scale; + srcRect.top = (dstRect.top - scaledTop) * 100 / scale; + srcRect.setWidth(dstRect.width() * 100 / scale); + srcRect.setHeight(dstRect.height() * 100 / scale); + if (!srcRect.isValidRect()) return; Common::Point dp; - dp.x = q.left + (r.width() * (100 - scale)) / 200; - dp.y = q.top + (r.height() * (100 - scale)) / 100; - q.translate(-r.left, -r.top); - byte *s = data + q.left + q.top * r.width(); + dp.x = dstRect.left; + dp.y = dstRect.top; + + byte *s = data + srcRect.left + srcRect.top * width; byte *d = (byte*)surf->getBasePtr(dp.x, dp.y); uint line = 0, col = 0; - for (uint16 i = 0; i < q.height(); i++) { + uint xAccum = 0, yAccum = 0; + uint inc = width * (100 - scale); + uint thr = width * 100; + + for (uint16 i = 0; i < srcRect.height(); i++) { yAccum += inc; if (yAccum >= thr) { yAccum -= thr; - s += r.width(); + s += width; continue; } @@ -312,7 +338,7 @@ void Gfx::bltMaskScale(const Common::Rect& r, byte *data, Graphics::Surface *sur byte *d2 = d; col = 0; - for (uint16 j = 0; j < q.width(); j++) { + for (uint16 j = 0; j < srcRect.width(); j++) { xAccum += inc; if (xAccum >= thr) { @@ -335,7 +361,7 @@ void Gfx::bltMaskScale(const Common::Rect& r, byte *data, Graphics::Surface *sur col++; } - s += r.width() - q.width(); + s += width - srcRect.width(); d += surf->w; line++; } diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp index bc1759ecd7..2990d024d2 100644 --- a/engines/parallaction/graphics.cpp +++ b/engines/parallaction/graphics.cpp @@ -317,8 +317,10 @@ void Gfx::drawList(Graphics::Surface &surface, GfxObjArray &list) { void Gfx::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) { if (_doubleBuffering) { - if (_overlayMode) + if (_overlayMode) { x += _scrollPosX; + y += _scrollPosY; + } byte *dst = (byte*)_backBuffer.getBasePtr(x, y); for (int i = 0; i < h; i++) { @@ -358,7 +360,7 @@ void Gfx::unlockScreen() { void Gfx::updateScreenIntern() { if (_doubleBuffering) { - byte *data = (byte*)_backBuffer.getBasePtr(_scrollPosX, 0); + byte *data = (byte*)_backBuffer.getBasePtr(_scrollPosX, _scrollPosY); _vm->_system->copyRectToScreen(data, _backBuffer.pitch, 0, 0, _vm->_screenWidth, _vm->_screenHeight); } @@ -863,6 +865,8 @@ void Gfx::setBackground(uint type, BackgroundInfo *info) { _minScrollX = 0; _maxScrollX = MAX<int>(0, _backgroundInfo->width - _vm->_screenWidth); + _minScrollY = 0; + _maxScrollY = MAX<int>(0, _backgroundInfo->height - _vm->_screenHeight); } diff --git a/engines/parallaction/gui_br.cpp b/engines/parallaction/gui_br.cpp index 7096bbe569..21cb2d8b00 100644 --- a/engines/parallaction/gui_br.cpp +++ b/engines/parallaction/gui_br.cpp @@ -98,6 +98,12 @@ public: } }; + +struct LocationPart { + int part; + const char *location; +}; + class MainMenuInputState_BR : public MenuInputState { Parallaction_br *_vm; @@ -158,7 +164,7 @@ class MainMenuInputState_BR : public MenuInputState { const char **_menuStrings; const MenuOptions *_options; - static const char *_firstLocation[]; + static LocationPart _firstLocation[]; int _availItems; int _selection; @@ -205,7 +211,8 @@ public: return this; } - switch (_options[_selection]) { + int selection = _options[_selection]; + switch (selection) { case kMenuQuit: { _vm->quitGame(); break; @@ -218,8 +225,10 @@ public: } break; - default: - _vm->scheduleLocationSwitch(_firstLocation[_options[_selection]]); + default: + _vm->_nextPart = _firstLocation[selection].part; + _vm->scheduleLocationSwitch(_firstLocation[selection].location); + } _vm->_system->showMouse(false); @@ -262,14 +271,15 @@ public: }; -const char *MainMenuInputState_BR::_firstLocation[] = { - "intro.0", - "museo.1", - "start.2", - "bolscoi.3", - "treno.4" +LocationPart MainMenuInputState_BR::_firstLocation[] = { + { 0, "intro" }, + { 1, "museo" }, + { 2, "start" }, + { 3, "bolscoi" }, + { 4, "treno" } }; + const char *MainMenuInputState_BR::_menuStringsAmiga[NUM_MENULINES] = { "See the introduction", "Load a Saved Game", diff --git a/engines/parallaction/input.cpp b/engines/parallaction/input.cpp index d6dd9feb19..6d3f6f0b04 100644 --- a/engines/parallaction/input.cpp +++ b/engines/parallaction/input.cpp @@ -395,7 +395,7 @@ void Input::exitInventoryMode() { _vm->dropItem(z->u._mergeObj1); _vm->dropItem(z->u._mergeObj2); _vm->addInventoryItem(z->u._mergeObj3); - _vm->_cmdExec->run(z->_commands); + _vm->_cmdExec->run(z->_commands); // commands might set a new _inputMode } } @@ -412,7 +412,11 @@ void Input::exitInventoryMode() { } _vm->resumeJobs(); - _inputMode = kInputModeGame; + // in case the input mode was not changed by the code above (especially by the commands + // executed in case of a merge), then assume we are going back to game mode + if (_inputMode == kInputModeInventory) { + _inputMode = kInputModeGame; + } } bool Input::updateInventoryInput() { diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h index 151bfd958d..7bbdf79f1c 100644 --- a/engines/parallaction/parallaction.h +++ b/engines/parallaction/parallaction.h @@ -548,6 +548,9 @@ public: const char **_audioCommandsNamesRes; static const char *_partNames[]; int _part; + int _nextPart; + + #if 0 // disabled since I couldn't find any references to lip sync in the scripts int16 _lipSyncVal; uint _subtitleLipSync; diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp index c752c85d4f..470c698a21 100644 --- a/engines/parallaction/parallaction_br.cpp +++ b/engines/parallaction/parallaction_br.cpp @@ -61,8 +61,8 @@ Common::Error Parallaction_br::init() { _disk = new DosDisk_br(this); } _disk->setLanguage(2); // NOTE: language is now hardcoded to English. Original used command-line parameters. - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - MidiDriver *driver = MidiDriver::createMidi(midiDriver); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); + MidiDriver *driver = MidiDriver::createMidi(dev); _soundManI = new DosSoundMan_br(this, driver); } else { _disk = new AmigaDisk_br(this); @@ -86,6 +86,7 @@ Common::Error Parallaction_br::init() { _walker = new PathWalker_BR; _part = -1; + _nextPart = -1; _subtitle[0] = 0; _subtitle[1] = 0; @@ -260,6 +261,12 @@ void Parallaction_br::cleanupGame() { _globalFlagsNames = 0; _objectsNames = 0; _countersNames = 0; + + _numLocations = 0; + _globalFlags = 0; + memset(_localFlags, 0, sizeof(_localFlags)); + memset(_locationNames, 0, sizeof(_locationNames)); + memset(_zoneFlags, 0, sizeof(_zoneFlags)); } @@ -268,17 +275,16 @@ void Parallaction_br::changeLocation() { return; } - char location[200]; - strcpy(location, _newLocationName.c_str()); - - char *partStr = strrchr(location, '.'); - if (partStr) { + if (_nextPart != -1) { cleanupGame(); - int n = partStr - location; - location[n] = '\0'; + // more cleanup needed for part changes (see also saveload) + _globalFlags = 0; + cleanInventory(true); + strcpy(_characterName1, "null"); + + _part = _nextPart; - _part = atoi(++partStr); if (getFeatures() & GF_DEMO) { assert(_part == 1); } else { @@ -305,8 +311,8 @@ void Parallaction_br::changeLocation() { freeLocation(false); // load new location - strcpy(_location._name, location); - parseLocation(location); + strcpy(_location._name, _newLocationName.c_str()); + parseLocation(_location._name); if (_location._startPosition.x != -1000) { _char._ani->setFoot(_location._startPosition); @@ -357,6 +363,7 @@ void Parallaction_br::changeLocation() { _engineFlags &= ~kEngineChangeLocation; _newLocationName.clear(); + _nextPart = -1; } // FIXME: Parallaction_br::parseLocation() is now a verbatim copy of the same routine from Parallaction_ns. diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp index c1d6c9367a..f1e7b14583 100644 --- a/engines/parallaction/parallaction_ns.cpp +++ b/engines/parallaction/parallaction_ns.cpp @@ -24,7 +24,6 @@ */ #include "common/system.h" - #include "common/config-manager.h" #include "parallaction/parallaction.h" @@ -167,8 +166,8 @@ Common::Error Parallaction_ns::init() { _disk->init(); if (getPlatform() == Common::kPlatformPC) { - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - MidiDriver *driver = MidiDriver::createMidi(midiDriver); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); + MidiDriver *driver = MidiDriver::createMidi(dev); _soundManI = new DosSoundMan_ns(this, driver); _soundManI->setMusicVolume(ConfMan.getInt("music_volume")); } else { diff --git a/engines/parallaction/parser.h b/engines/parallaction/parser.h index 3e46e99180..5eb26e9fa1 100644 --- a/engines/parallaction/parser.h +++ b/engines/parallaction/parser.h @@ -294,6 +294,7 @@ public: virtual void parseGetData(ZonePtr z); virtual void parseDoorData(ZonePtr z); virtual void parseHearData(ZonePtr z); + virtual void parseNoneData(ZonePtr z); protected: void parseAnswerCounter(Answer *answer); virtual Answer *parseAnswer(); diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp index d3ce1235c1..57259fd637 100644 --- a/engines/parallaction/parser_br.cpp +++ b/engines/parallaction/parser_br.cpp @@ -825,6 +825,16 @@ void LocationParser_br::parseHearData(ZonePtr z) { } } +void LocationParser_br::parseNoneData(ZonePtr z) { + /* the only case we have to handle here is that of "scende2", which is the only Animation with + a command list following the type marker. + */ + if (!scumm_stricmp(_tokens[0], "commands")) { + parseCommands(z->_commands); + } +} + + typedef void (LocationParser_br::*ZoneTypeParser)(ZonePtr); static ZoneTypeParser parsers[] = { 0, // no type @@ -836,7 +846,7 @@ static ZoneTypeParser parsers[] = { &LocationParser_br::parseHearData, 0, // feel &LocationParser_br::parseSpeakData, - 0, // none + &LocationParser_br::parseNoneData, 0, // trap 0, // you 0, // command @@ -882,7 +892,6 @@ DECLARE_ANIM_PARSER(moveto) { // ctxt.a->_moveTo.z = atoi(_tokens[3]); } - DECLARE_ANIM_PARSER(endanimation) { debugC(7, kDebugParser, "ANIM_PARSER(endanimation) "); diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp index 8fc916e490..d6df23d415 100644 --- a/engines/parallaction/walk.cpp +++ b/engines/parallaction/walk.cpp @@ -450,7 +450,7 @@ void PathWalker_BR::buildPath(State &s, uint16 x, uint16 y) { Common::Point foot; s._a->getFoot(foot); - debugC(1, kDebugWalk, "buildPath: from (%i, %i) to (%i, %i)", foot.x, foot.y, x, y); + debugC(1, kDebugWalk, "buildPath: try to build path from (%i, %i) to (%i, %i)", foot.x, foot.y, x, y); s._walkPath.clear(); // look for easy path first @@ -465,13 +465,13 @@ void PathWalker_BR::buildPath(State &s, uint16 x, uint16 y) { ZonePtr z0 = _vm->hitZone(kZonePath, x, y); if (!z0) { s._walkPath.push_back(dest); - debugC(3, kDebugWalk, "buildPath: corner case 0"); + debugC(3, kDebugWalk, "buildPath: corner case 0 (%i nodes)", s._walkPath.size()); return; } ZonePtr z1 = _vm->hitZone(kZonePath, foot.x, foot.y); if (!z1 || z1 == z0) { s._walkPath.push_back(dest); - debugC(3, kDebugWalk, "buildPath: corner case 1"); + debugC(3, kDebugWalk, "buildPath: corner case 1 (%i nodes)", s._walkPath.size()); return; } @@ -480,7 +480,7 @@ void PathWalker_BR::buildPath(State &s, uint16 x, uint16 y) { if (z1->u._pathLists[id].empty()) { s._walkPath.clear(); - debugC(3, kDebugWalk, "buildPath: no path"); + debugC(3, kDebugWalk, "buildPath: no path found"); return; } @@ -490,7 +490,7 @@ void PathWalker_BR::buildPath(State &s, uint16 x, uint16 y) { s._walkPath.push_front(*b); } s._walkPath.push_back(dest); - debugC(3, kDebugWalk, "buildPath: complex path"); + debugC(3, kDebugWalk, "buildPath: complex path (%i nodes)", s._walkPath.size()); } @@ -541,8 +541,6 @@ void PathWalker_BR::walk() { return; } - debugC(3, kDebugWalk, "PathWalker_BR::walk()"); - doWalk(_character); doWalk(_follower); @@ -566,8 +564,6 @@ void PathWalker_BR::walk() { } _vm->_gfx->initiateScroll(dx, dy); - - debugC(3, kDebugWalk, "PathWalker_BR::walk() -> done"); } void PathWalker_BR::checkTrap(const Common::Point &p) { @@ -601,8 +597,6 @@ void PathWalker_BR::doWalk(State &s) { return; } - debugC(3, kDebugWalk, "PathWalker_BR::doWalk(%s)", s._a->_name); - if (s._walkDelay > 0) { s._walkDelay--; if (s._walkDelay == 0 && s._a->_scriptName) { @@ -619,10 +613,10 @@ void PathWalker_BR::doWalk(State &s) { if (s._walkPath.empty()) { finalizeWalk(s); - debugC(3, kDebugWalk, "PathWalker_BR::doWalk, case 0"); + debugC(3, kDebugWalk, "PathWalker_BR::doWalk, walk completed (no more nodes)"); return; } else { - debugC(3, kDebugWalk, "PathWalker_BR::doWalk, moving to next node"); + debugC(3, kDebugWalk, "PathWalker_BR::doWalk, reached a walkpath node, %i left", s._walkPath.size()); } } @@ -632,6 +626,19 @@ void PathWalker_BR::doWalk(State &s) { int xStep = (scale * 16) / 100 + 1; int yStep = (scale * 10) / 100 + 1; + + /* WORKAROUND: in the balloon scene, the position of the balloon (which is implemented as a + Character) is controlled by the user (for movement, via this walking code) and by the scripts + (to simulate the balloon floating in the air, in a neverending loop that alters the position + coordinates). + When the two step sizes are equal in magnitude and opposite in direction, then the walk code + enters an infinite loop without giving control back to the user (this happens quite frequently + when navigating the balloon near the borders of the screen, where the calculated step is + forcibly small because of clipping). Since the "floating" script (part1/scripts/mongolo.scr) + uses increments of 3 for both x and y, we tweak the calculated steps accordingly here. */ + if (xStep == 3) xStep--; + if (yStep == 3) yStep--; + debugC(9, kDebugWalk, "calculated step: (%i, %i)", xStep, yStep); s._fieldC = 0; @@ -714,7 +721,7 @@ void PathWalker_BR::doWalk(State &s) { Common::Point p2; s._a->getFoot(p2); checkTrap(p2); - debugC(3, kDebugWalk, "PathWalker_BR::doWalk, case 1"); + debugC(3, kDebugWalk, "PathWalker_BR::doWalk, stepped to (%i, %i)", p2.x, p2.y); return; } diff --git a/engines/queen/music.cpp b/engines/queen/music.cpp index b4b9210616..3d859c8335 100644 --- a/engines/queen/music.cpp +++ b/engines/queen/music.cpp @@ -34,6 +34,7 @@ #include "sound/midiparser.h" + namespace Queen { extern MidiDriver *C_Player_CreateAdLibMidiDriver(Audio::Mixer *); @@ -45,9 +46,9 @@ MidiMusic::MidiMusic(QueenEngine *vm) _queuePos = _lastSong = _currentSong = 0; queueClear(); - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - _adlib = (midiDriver == MD_ADLIB); - _nativeMT32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MT32); + _adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB); + _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); const char *musicDataFile; if (vm->resource()->isDemo()) { @@ -72,7 +73,7 @@ MidiMusic::MidiMusic(QueenEngine *vm) // } _driver = C_Player_CreateAdLibMidiDriver(vm->_mixer); } else { - _driver = MidiDriver::createMidi(midiDriver); + _driver = MidiDriver::createMidi(dev); if (_nativeMT32) { _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); } diff --git a/engines/saga/actor.cpp b/engines/saga/actor.cpp index c3f5fec83a..8bc8025032 100644 --- a/engines/saga/actor.cpp +++ b/engines/saga/actor.cpp @@ -1173,7 +1173,9 @@ void Actor::drawActors() { return; } - if (_vm->_anim->hasCutaway()) { + // WORKAROUND + // Bug #2928923: 'ITE: Graphic Glitches during racoon death "Cut Scene"' + if (_vm->_anim->hasCutaway() || _vm->_scene->currentSceneNumber() == 287 || _vm->_scene->currentSceneNumber() == 286) { drawSpeech(); return; } diff --git a/engines/saga/console.cpp b/engines/saga/console.cpp index 2c201ac57d..228febfe9c 100644 --- a/engines/saga/console.cpp +++ b/engines/saga/console.cpp @@ -40,9 +40,6 @@ Console::Console(SagaEngine *vm) : GUI::Debugger() { DCmd_Register("continue", WRAP_METHOD(Console, Cmd_Exit)); - // CVAR_Register_I(&_soundEnabled, "sound", NULL, CVAR_CFG, 0, 1); - // CVAR_Register_I(&_musicEnabled, "music", NULL, CVAR_CFG, 0, 1); - // Actor commands DCmd_Register("actor_walk_to", WRAP_METHOD(Console, cmdActorWalkTo)); diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp index 1c2c6bacff..7913291527 100644 --- a/engines/saga/detection.cpp +++ b/engines/saga/detection.cpp @@ -122,7 +122,11 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NONE + Common::GUIO_NONE, + // Maximum directory depth + 1, + // List of directory globs + 0 }; class SagaMetaEngine : public AdvancedMetaEngine { diff --git a/engines/saga/events.cpp b/engines/saga/events.cpp index d15f0b2af3..1f4091d07c 100644 --- a/engines/saga/events.cpp +++ b/engines/saga/events.cpp @@ -306,7 +306,6 @@ int Events::handleOneShot(Event *event) { _vm->_sndRes->playVoice(event->param); break; case kMusicEvent: - _vm->_music->stop(); if (event->op == kEventPlay) _vm->_music->play(event->param, (MusicFlags)event->param2); break; diff --git a/engines/saga/font.h b/engines/saga/font.h index f290384e87..d8b1da30b9 100644 --- a/engines/saga/font.h +++ b/engines/saga/font.h @@ -190,7 +190,7 @@ class Font { } } bool valid(FontId fontId) { - return ((fontId >= 0) && (fontId < _loadedFonts)); + return (fontId < _loadedFonts); } int getByteLen(int numBits) const { int byteLength = numBits / 8; diff --git a/engines/saga/interface.cpp b/engines/saga/interface.cpp index c0d3cee465..c4b4688785 100644 --- a/engines/saga/interface.cpp +++ b/engines/saga/interface.cpp @@ -544,8 +544,10 @@ bool Interface::processAscii(Common::KeyState keystate) { return true; } +#ifdef ENABLE_IHNM if (_vm->_scene->isNonInteractiveIHNMDemoPart()) _vm->_scene->showIHNMDemoSpecialScreen(); +#endif break; case kPanelCutaway: if (keystate.keycode == Common::KEYCODE_ESCAPE) { @@ -555,8 +557,10 @@ bool Interface::processAscii(Common::KeyState keystate) { return true; } +#ifdef ENABLE_INHM if (_vm->_scene->isNonInteractiveIHNMDemoPart()) _vm->_scene->showIHNMDemoSpecialScreen(); +#endif break; case kPanelVideo: if (keystate.keycode == Common::KEYCODE_ESCAPE) { @@ -570,8 +574,10 @@ bool Interface::processAscii(Common::KeyState keystate) { return true; } +#ifdef ENABLE_IHNM if (_vm->_scene->isNonInteractiveIHNMDemoPart()) _vm->_scene->showIHNMDemoSpecialScreen(); +#endif break; case kPanelOption: // TODO: check input dialog keys @@ -1855,6 +1861,7 @@ void Interface::update(const Point& mousePoint, int updateFlag) { if (updateFlag & UPDATE_MOUSECLICK) { if (!_vm->isIHNMDemo()) { _vm->_scene->clearPsychicProfile(); + _vm->_script->wakeUpThreads(kWaitTypeDelay); } else { setMode(kPanelConverse); _vm->_scene->_textList.clear(); @@ -1866,8 +1873,10 @@ void Interface::update(const Point& mousePoint, int updateFlag) { break; case kPanelNull: +#ifdef ENABLE_IHNM if (_vm->_scene->isNonInteractiveIHNMDemoPart() && (updateFlag & UPDATE_MOUSECLICK)) _vm->_scene->showIHNMDemoSpecialScreen(); +#endif break; } diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index 75c5cdffd7..8b7654d689 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -42,19 +42,25 @@ namespace Saga { #define BUFFER_SIZE 4096 #define MUSIC_SUNSPOT 26 -MusicPlayer::MusicPlayer(MidiDriver *driver) : _parser(0), _driver(driver), _looping(false), _isPlaying(false), _passThrough(false), _isGM(false) { +MusicDriver::MusicDriver() : _isGM(false) { memset(_channel, 0, sizeof(_channel)); _masterVolume = 0; + _nativeMT32 = ConfMan.getBool("native_mt32"); + + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); + _driver = MidiDriver::createMidi(dev); + if (isMT32()) + _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); + this->open(); } -MusicPlayer::~MusicPlayer() { - _driver->setTimerCallback(NULL, NULL); - stopMusic(); +MusicDriver::~MusicDriver() { this->close(); + delete _driver; } -void MusicPlayer::setVolume(int volume) { +void MusicDriver::setVolume(int volume) { volume = CLIP(volume, 0, 255); if (_masterVolume == volume) @@ -71,32 +77,7 @@ void MusicPlayer::setVolume(int volume) { } } -int MusicPlayer::open() { - // Don't ever call open without first setting the output driver! - if (!_driver) - return 255; - - int ret = _driver->open(); - if (ret) - return ret; - - _driver->setTimerCallback(this, &onTimer); - return 0; -} - -void MusicPlayer::close() { - stopMusic(); - if (_driver) - _driver->close(); - _driver = 0; -} - -void MusicPlayer::send(uint32 b) { - if (_passThrough) { - _driver->send(b); - return; - } - +void MusicDriver::send(uint32 b) { byte channel = (byte)(b & 0x0F); if ((b & 0xFFF0) == 0x07B0) { // Adjust volume changes by master volume @@ -104,71 +85,86 @@ void MusicPlayer::send(uint32 b) { _channelVolume[channel] = volume; volume = volume * _masterVolume / 255; b = (b & 0xFF00FFFF) | (volume << 16); - } else if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) { + } else if ((b & 0xF0) == 0xC0 && !_isGM && !isMT32()) { + // Remap MT32 instruments to General Midi b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8; - } - else if ((b & 0xFFF0) == 0x007BB0) { - //Only respond to All Notes Off if this channel - //has currently been allocated - if (_channel[b & 0x0F]) + } else if ((b & 0xFFF0) == 0x007BB0) { + // Only respond to All Notes Off if this channel + // has currently been allocated + if (!_channel[channel]) return; } if (!_channel[channel]) _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel(); - - if (_channel[channel]) + else _channel[channel]->send(b); } -void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) { - // FIXME: The "elkfanfare" is played much too quickly. There are some - // meta events that we don't handle. Perhaps there is a - // connection...? - - switch (type) { - case 0x2F: // End of Track - if (_looping) - _parser->jumpToTick(0); - else - stopMusic(); - break; - default: - //warning("Unhandled meta event: %02x", type); - break; - } -} - -void MusicPlayer::onTimer(void *refCon) { - MusicPlayer *music = (MusicPlayer *)refCon; - Common::StackLock lock(music->_mutex); - - if (music->_isPlaying) - music->_parser->onTimer(); -} - -void MusicPlayer::playMusic() { - _isPlaying = true; -} +Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) { + _currentVolume = 0; + _driver = new MusicDriver(); -void MusicPlayer::stopMusic() { - Common::StackLock lock(_mutex); + _digitalMusicContext = _vm->_resource->getContext(GAME_DIGITALMUSICFILE); + if (!_driver->isAdlib()) + _musicContext = _vm->_resource->getContext(GAME_MUSICFILE_GM); + else + _musicContext = _vm->_resource->getContext(GAME_MUSICFILE_FM); - _isPlaying = false; - if (_parser) { - _parser->unloadMusic(); - _parser = NULL; + if (!_musicContext) { + if (_vm->getGameId() == GID_ITE) { + _musicContext = _vm->_resource->getContext(GAME_RESOURCEFILE); + } else { + // I've listened to music from both the FM and the GM + // file, and I've tentatively reached the conclusion + // that they are both General MIDI. My guess is that + // the FM file has been reorchestrated to sound better + // on AdLib and other FM synths. + // + // Sev says the AdLib music does not sound like in the + // original, but I still think assuming General MIDI is + // the right thing to do. Some music, like the End + // Title (song 0) sound absolutely atrocious when piped + // through our MT-32 to GM mapping. + // + // It is, however, quite possible that the original + // used a different GM to FM mapping. If the original + // sounded markedly better, perhaps we should add some + // way of replacing our stock mapping in adlib.cpp? + // + // For the composer's own recording of the End Title, + // see http://www.johnottman.com/ + + // Oddly enough, the intro music (song 1) is very + // different in the two files. I have no idea why. + // Note that the IHNM demo has only got one music file + // (music.rsc). It is assumed that it contains FM music + _musicContext = _vm->_resource->getContext(GAME_MUSICFILE_FM); + } } -} -Music::Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver) : _vm(vm), _mixer(mixer), _adlib(false) { - _player = new MusicPlayer(driver); - _currentVolume = 0; - - xmidiParser = MidiParser::createParser_XMIDI(); - smfParser = MidiParser::createParser_SMF(); + // Check if the game is using XMIDI or SMF music + if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) { + // Just set an XMIDI parser for Mac IHNM for now + _parser = MidiParser::createParser_XMIDI(); + } else { + byte *resourceData; + size_t resourceSize; + int resourceId = (_vm->getGameId() == GID_ITE ? 9 : 0); + _vm->_resource->loadResource(_musicContext, resourceId, resourceData, resourceSize); + if (!memcmp(resourceData, "FORM", 4)) { + _parser = MidiParser::createParser_XMIDI(); + // ITE had MT32 mapped instruments + _driver->setGM(_vm->getGameId() != GID_ITE); + } else { + _parser = MidiParser::createParser_SMF(); + } + free(resourceData); + } - _digitalMusicContext = _vm->_resource->getContext(GAME_DIGITALMUSICFILE); + _parser->setMidiDriver(_driver); + _parser->setTimerRate(_driver->getBaseTempo()); + _parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); _songTableLen = 0; _songTable = 0; @@ -180,11 +176,11 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver) : _vm(vm), Music::~Music() { _vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback); _mixer->stopHandle(_musicHandle); - delete _player; - xmidiParser->setMidiDriver(NULL); - smfParser->setMidiDriver(NULL); - delete xmidiParser; - delete smfParser; + _driver->setTimerCallback(NULL, NULL); + _driver->close(); + delete _driver; + _parser->setMidiDriver(NULL); + delete _parser; free(_songTable); free(_midiMusicData); @@ -194,6 +190,12 @@ void Music::musicVolumeGaugeCallback(void *refCon) { ((Music *)refCon)->musicVolumeGauge(); } +void Music::onTimer(void *refCon) { + Music *music = (Music *)refCon; + Common::StackLock lock(music->_driver->_mutex); + music->_parser->onTimer(); +} + void Music::musicVolumeGauge() { int volume; @@ -209,7 +211,7 @@ void Music::musicVolumeGauge() { volume = 1; _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume); - _player->setVolume(volume); + _driver->setVolume(volume); if (_currentVolumePercent == 100) { _vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback); @@ -226,23 +228,21 @@ void Music::setVolume(int volume, int time) { if (time == 1) { _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume); - _player->setVolume(volume); + _driver->setVolume(volume); _vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback); _currentVolume = volume; return; } - _vm->getTimerManager()->installTimerProc(&musicVolumeGaugeCallback, time * 100L, this); + _vm->getTimerManager()->installTimerProc(&musicVolumeGaugeCallback, time * 3000L, this); } bool Music::isPlaying() { - return _mixer->isSoundHandleActive(_musicHandle) || _player->isPlaying(); + return _mixer->isSoundHandleActive(_musicHandle) || _parser->isPlaying(); } void Music::play(uint32 resourceId, MusicFlags flags) { Audio::SeekableAudioStream *audioStream = NULL; - MidiParser *parser; - ResourceContext *context = NULL; byte *resourceData; size_t resourceSize; uint32 loopStart; @@ -254,8 +254,8 @@ void Music::play(uint32 resourceId, MusicFlags flags) { } _trackNumber = resourceId; - _player->stopMusic(); _mixer->stopHandle(_musicHandle); + _parser->unloadMusic(); int realTrackNumber; @@ -356,55 +356,10 @@ void Music::play(uint32 resourceId, MusicFlags flags) { return; } - if (flags == MUSIC_DEFAULT) { + if (flags == MUSIC_DEFAULT) flags = MUSIC_NORMAL; - } // Load MIDI/XMI resource data - - if (_vm->getGameId() == GID_ITE) { - context = _vm->_resource->getContext(GAME_MUSICFILE_GM); - if (context == NULL) { - context = _vm->_resource->getContext(GAME_RESOURCEFILE); - } - } else if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) { - // The music of the Mac version of IHNM is loaded from its - // associated external file later on - } else { - // I've listened to music from both the FM and the GM - // file, and I've tentatively reached the conclusion - // that they are both General MIDI. My guess is that - // the FM file has been reorchestrated to sound better - // on AdLib and other FM synths. - // - // Sev says the AdLib music does not sound like in the - // original, but I still think assuming General MIDI is - // the right thing to do. Some music, like the End - // Title (song 0) sound absolutely atrocious when piped - // through our MT-32 to GM mapping. - // - // It is, however, quite possible that the original - // used a different GM to FM mapping. If the original - // sounded markedly better, perhaps we should add some - // way of replacing our stock mapping in adlib.cpp? - // - // For the composer's own recording of the End Title, - // see http://www.johnottman.com/ - - // Oddly enough, the intro music (song 1) is very - // different in the two files. I have no idea why. - // Note that the IHNM demo has only got one music file - // (music.rsc). It is assumed that it contains FM music - - if (hasAdLib() || _vm->isIHNMDemo()) { - context = _vm->_resource->getContext(GAME_MUSICFILE_FM); - } else { - context = _vm->_resource->getContext(GAME_MUSICFILE_GM); - } - } - - _player->setGM(true); - if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) { // Load the external music file for Mac IHNM #if 0 @@ -422,56 +377,39 @@ void Music::play(uint32 resourceId, MusicFlags flags) { #endif return; } else { - _vm->_resource->loadResource(context, resourceId, resourceData, resourceSize); + _vm->_resource->loadResource(_musicContext, resourceId, resourceData, resourceSize); } if (resourceSize < 4) { error("Music::play() wrong music resource size"); } - if (xmidiParser->loadMusic(resourceData, resourceSize)) { - if (_vm->getGameId() == GID_ITE) - _player->setGM(false); + if (!_parser->loadMusic(resourceData, resourceSize)) + error("Music::play() wrong music resource"); - parser = xmidiParser; - } else { - if (smfParser->loadMusic(resourceData, resourceSize)) { - parser = smfParser; - } else { - error("Music::play() wrong music resource"); - } - } - - parser->setTrack(0); - parser->setMidiDriver(_player); - parser->setTimerRate(_player->getBaseTempo()); - parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); + _parser->setTrack(0); + _driver->setTimerCallback(this, &onTimer); - _player->_parser = parser; setVolume(_vm->_musicVolume); - if (flags & MUSIC_LOOP) - _player->setLoop(true); - else - _player->setLoop(false); + // Handle music looping + _parser->property(MidiParser::mpAutoLoop, (flags & MUSIC_LOOP) ? 1 : 0); - _player->playMusic(); free(_midiMusicData); _midiMusicData = resourceData; } void Music::pause() { - _player->setVolume(-1); - _player->setPlaying(false); + _driver->setTimerCallback(NULL, NULL); } void Music::resume() { - _player->setVolume(_vm->_musicVolume); - _player->setPlaying(true); + _driver->setTimerCallback(this, &onTimer); } void Music::stop() { - _player->stopMusic(); + _driver->setTimerCallback(NULL, NULL); + _parser->unloadMusic(); } } // End of namespace Saga diff --git a/engines/saga/music.h b/engines/saga/music.h index 131078a9c3..f3b0f177b0 100644 --- a/engines/saga/music.h +++ b/engines/saga/music.h @@ -44,41 +44,32 @@ enum MusicFlags { MUSIC_DEFAULT = 0xffff }; -class MusicPlayer : public MidiDriver { +class MusicDriver : public MidiDriver { public: - MusicPlayer(MidiDriver *driver); - ~MusicPlayer(); - - bool isPlaying() { return _isPlaying; } - void setPlaying(bool playing) { _isPlaying = playing; } + MusicDriver(); + ~MusicDriver(); void setVolume(int volume); int getVolume() { return _masterVolume; } - void setNativeMT32(bool b) { _nativeMT32 = b; } - bool hasNativeMT32() { return _nativeMT32; } - void playMusic(); - void stopMusic(); - void setLoop(bool loop) { _looping = loop; } - void setPassThrough(bool b) { _passThrough = b; } - + bool isAdlib() { return _driverType == MT_ADLIB; } + bool isMT32() { return _driverType == MT_MT32 || _nativeMT32; } void setGM(bool isGM) { _isGM = isGM; } //MidiDriver interface implementation - int open(); - void close(); + int open() { return _driver->open(); } + void close() { _driver->close(); } void send(uint32 b); - void metaEvent(byte type, byte *data, uint16 length); + void metaEvent(byte type, byte *data, uint16 length) {} - void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { } - uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; } + void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { _driver->setTimerCallback(timerParam, timerProc); } + uint32 getBaseTempo() { return _driver->getBaseTempo(); } //Channel allocation functions MidiChannel *allocateChannel() { return 0; } MidiChannel *getPercussionChannel() { return 0; } - MidiParser *_parser; Common::Mutex _mutex; protected: @@ -87,14 +78,11 @@ protected: MidiChannel *_channel[16]; MidiDriver *_driver; + MusicType _driverType; byte _channelVolume[16]; - bool _nativeMT32; bool _isGM; - bool _passThrough; + bool _nativeMT32; - bool _isPlaying; - bool _looping; - bool _randomLoop; byte _masterVolume; byte *_musicData; @@ -105,13 +93,8 @@ protected: class Music { public: - Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver); + Music(SagaEngine *vm, Audio::Mixer *mixer); ~Music(); - void setNativeMT32(bool b) { _player->setNativeMT32(b); } - bool hasNativeMT32() { return _player->hasNativeMT32(); } - void setAdLib(bool b) { _adlib = b; } - bool hasAdLib() { return _adlib; } - void setPassThrough(bool b) { _player->setPassThrough(b); } bool isPlaying(); bool hasDigitalMusic() { return _digitalMusic; } @@ -130,24 +113,23 @@ private: SagaEngine *_vm; Audio::Mixer *_mixer; - MusicPlayer *_player; + MusicDriver *_driver; Audio::SoundHandle _musicHandle; uint32 _trackNumber; - bool _adlib; - int _targetVolume; int _currentVolume; int _currentVolumePercent; bool _digitalMusic; + ResourceContext *_musicContext; ResourceContext *_digitalMusicContext; - MidiParser *xmidiParser; - MidiParser *smfParser; + MidiParser *_parser; byte *_midiMusicData; static void musicVolumeGaugeCallback(void *refCon); + static void onTimer(void *refCon); void musicVolumeGauge(); }; diff --git a/engines/saga/puzzle.cpp b/engines/saga/puzzle.cpp index 957ab3c8b6..5b13473d77 100644 --- a/engines/saga/puzzle.cpp +++ b/engines/saga/puzzle.cpp @@ -411,12 +411,12 @@ void Puzzle::solicitHint() { switch (_hintRqState) { case kRQSpeaking: if (_vm->_actor->isSpeaking()) { - _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50000, this); + _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50 * 1000000, this); break; } _hintRqState = _hintNextRqState; - _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 333333, this); + _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 100*1000000/3, this); break; case kRQNoHint: @@ -439,11 +439,11 @@ void Puzzle::solicitHint() { // Roll to see if Sakka scolds if (_vm->_rnd.getRandomNumber(1)) { _hintRqState = kRQSakkaDenies; - _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 200000, this); + _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 200*1000000, this); } else { _hintRqState = kRQSpeaking; _hintNextRqState = kRQHintRequested; - _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50000, this); + _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50*1000000, this); } break; @@ -456,7 +456,7 @@ void Puzzle::solicitHint() { _hintRqState = kRQSpeaking; _hintNextRqState = kRQHintRequestedStage2; - _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50000, this); + _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50*1000000, this); _vm->_interface->converseClear(); _vm->_interface->converseAddText(optionsStr[_lang][kROAccept], 0, 1, 0, 0 ); diff --git a/engines/saga/render.cpp b/engines/saga/render.cpp index ec168d296e..dc9334b037 100644 --- a/engines/saga/render.cpp +++ b/engines/saga/render.cpp @@ -110,6 +110,12 @@ void Render::drawScene() { _vm->_actor->drawActors(); } + // WORKAROUND + // Bug #2886130: "ITE: Graphic Glitches during Cat Tribe Celebration" + if (_vm->_scene->currentSceneNumber() == 274) { + _vm->_interface->drawStatusBar(); + } + #ifdef SAGA_DEBUG if (getFlags() & RF_OBJECTMAP_TEST) { if (_vm->_scene->_objectMap) diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp index ed8a9055ba..d1ab3bc9d7 100644 --- a/engines/saga/saga.cpp +++ b/engines/saga/saga.cpp @@ -83,7 +83,6 @@ SagaEngine::SagaEngine(OSystem *syst, const SAGAGameDescription *gameDesc) _sndRes = NULL; _sound = NULL; _music = NULL; - _driver = NULL; _anim = NULL; _render = NULL; _isoMap = NULL; @@ -198,9 +197,6 @@ SagaEngine::~SagaEngine() { delete _sound; _sound = NULL; - delete _driver; - _driver = NULL; - delete _gfx; _gfx = NULL; @@ -285,17 +281,7 @@ Common::Error SagaEngine::run() { _console = new Console(this); // Graphics should be initialized before music - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); - bool adlib = (midiDriver == MD_ADLIB); - - _driver = MidiDriver::createMidi(midiDriver); - if (native_mt32) - _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); - - _music = new Music(this, _mixer, _driver); - _music->setNativeMT32(native_mt32); - _music->setAdLib(adlib); + _music = new Music(this, _mixer); _render = new Render(this, _system); if (!_render->initialized()) { return Common::kUnknownError; @@ -433,7 +419,7 @@ void SagaEngine::loadStrings(StringsTable &stringsTable, const byte *stringsPoin offset = scriptS.readUint16(); // In some rooms in IHNM, string offsets can be greater than the maximum value than a 16-bit integer can hold // We detect this by checking the previous offset, and if it was bigger than the current one, an overflow - // occured (since the string offsets are sequential), so we're adding the missing part of the number + // occurred (since the string offsets are sequential), so we're adding the missing part of the number // Fixes bug #1895205 - "IHNM: end game text/caption error" if (prevOffset > offset) offset += 65536; diff --git a/engines/saga/saga.h b/engines/saga/saga.h index 2bef489e05..102d1e5c82 100644 --- a/engines/saga/saga.h +++ b/engines/saga/saga.h @@ -525,7 +525,6 @@ public: SndRes *_sndRes; Sound *_sound; Music *_music; - MidiDriver *_driver; Anim *_anim; Render *_render; IsoMap *_isoMap; diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp index 40ee1fb720..d7ee037c50 100644 --- a/engines/saga/scene.cpp +++ b/engines/saga/scene.cpp @@ -1201,6 +1201,12 @@ void Scene::endScene() { _vm->_script->abortAllThreads(); _vm->_script->_skipSpeeches = false; + // WORKAROUND: Bug #2886151: "ITE: Mouse stops responding at Boar Castle" + // This is bug in original engine + if (_sceneNumber == 50) { + _vm->_interface->activate(); + } + // Copy current screen to render buffer so inset rooms will get proper background if (!(_sceneDescription.flags & kSceneFlagISO) && !_vm->_scene->isInIntro()) { BGInfo bgInfo; @@ -1425,6 +1431,8 @@ void Scene::clearPlacard() { q_event = _vm->_events->chain(q_event, &event); } +#ifdef ENABLE_IHNM + void Scene::showPsychicProfile(const char *text) { int textHeight; static PalEntry cur_pal[PAL_ENTRIES]; @@ -1440,6 +1448,8 @@ void Scene::showPsychicProfile(const char *text) { _vm->_interface->setMode(kPanelPlacard); _vm->_gfx->savePalette(); + _vm->_events->clearList(); + event.type = kEvTOneshot; event.code = kCursorEvent; event.op = kEventHide; @@ -1531,4 +1541,6 @@ void Scene::showIHNMDemoSpecialScreen() { _vm->_scene->changeScene(150, 0, kTransitionFade); } +#endif // IHNM + } // End of namespace Saga diff --git a/engines/saga/script.h b/engines/saga/script.h index f31af7b2ea..21afeb5c44 100644 --- a/engines/saga/script.h +++ b/engines/saga/script.h @@ -246,16 +246,19 @@ public: } void waitWalk(void *threadObj) { + debug(3, "waitWalk()"); wait(kWaitTypeWalk); _threadObj = threadObj; } void waitDelay(int sleepTime) { + debug(3, "waitDelay(%d)", sleepTime); wait(kWaitTypeDelay); _sleepTime = sleepTime; } void waitFrames(int frames) { + debug(3, "waitFrames(%d)", frames); wait(kWaitTypeWaitFrames); _frameWait = frames; } diff --git a/engines/saga/sfuncs.cpp b/engines/saga/sfuncs.cpp index f98a80acd8..328d4040af 100644 --- a/engines/saga/sfuncs.cpp +++ b/engines/saga/sfuncs.cpp @@ -370,12 +370,15 @@ void Script::sfStopBgdAnim(SCRIPTFUNC_PARAMS) { // reenabled. // Param1: boolean void Script::sfLockUser(SCRIPTFUNC_PARAMS) { - if (thread->pop()) { + int16 param = thread->pop(); + + if (param != 0) { _vm->_interface->deactivate(); } else { _vm->_interface->activate(); } + debug(1, "sfLockUser(%d)", param); } // Script function #12 (0x0C) @@ -1153,18 +1156,6 @@ void Script::sfPlacardOff(SCRIPTFUNC_PARAMS) { _vm->_scene->clearPlacard(); } -void Script::sfPsychicProfile(SCRIPTFUNC_PARAMS) { - thread->wait(kWaitTypePlacard); - - _vm->_scene->showPsychicProfile(thread->_strings->getString(thread->pop())); -} - -void Script::sfPsychicProfileOff(SCRIPTFUNC_PARAMS) { - // This is called a while after the psychic profile is - // opened, to close it automatically - _vm->_scene->clearPsychicProfile(); -} - // Script function #50 (0x32) void Script::sfSetProtagState(SCRIPTFUNC_PARAMS) { _vm->_actor->setProtagState(thread->pop()); @@ -1473,6 +1464,8 @@ void Script::sfPlayLoopedSound(SCRIPTFUNC_PARAMS) { } else { _vm->_sound->stopSound(); } + + debug(1, "sfPlayLoopedSound(%d)", param); } // Script function #72 (0x48) diff --git a/engines/saga/sfuncs_ihnm.cpp b/engines/saga/sfuncs_ihnm.cpp index fe586b54ae..b98c1cb852 100644 --- a/engines/saga/sfuncs_ihnm.cpp +++ b/engines/saga/sfuncs_ihnm.cpp @@ -440,6 +440,18 @@ void Script::sfDisableAbortSpeeches(SCRIPTFUNC_PARAMS) { _vm->_interface->disableAbortSpeeches(thread->pop() != 0); } +void Script::sfPsychicProfile(SCRIPTFUNC_PARAMS) { + thread->wait(kWaitTypePlacard); + + _vm->_scene->showPsychicProfile(thread->_strings->getString(thread->pop())); +} + +void Script::sfPsychicProfileOff(SCRIPTFUNC_PARAMS) { + // This is called a while after the psychic profile is + // opened, to close it automatically + _vm->_scene->clearPsychicProfile(); +} + } // End of namespace Saga #endif diff --git a/engines/saga/sndres.cpp b/engines/saga/sndres.cpp index 8ea3fc4003..a27608dcf5 100644 --- a/engines/saga/sndres.cpp +++ b/engines/saga/sndres.cpp @@ -159,7 +159,7 @@ void SndRes::playSound(uint32 resourceId, int volume, bool loop) { return; } - _vm->_sound->playSound(buffer, volume, loop); + _vm->_sound->playSound(buffer, volume, loop, resourceId); } void SndRes::playVoice(uint32 resourceId) { diff --git a/engines/saga/sound.cpp b/engines/saga/sound.cpp index 811ee709f7..db979e8104 100644 --- a/engines/saga/sound.cpp +++ b/engines/saga/sound.cpp @@ -105,10 +105,20 @@ void Sound::playSoundBuffer(Audio::SoundHandle *handle, const SoundBuffer &buffe _mixer->playStream(soundType, handle, Audio::makeLoopingAudioStream(stream, loop ? 0 : 1), -1, volume); } -void Sound::playSound(SoundBuffer &buffer, int volume, bool loop) { +void Sound::playSound(SoundBuffer &buffer, int volume, bool loop, int resId) { + // WORKAROUND + // Prevent playing same looped sound for several times + // Fixes bug #2886141: "ITE: Cumulative Snoring sounds in Prince's Bedroom" + for (int i = 0; i < SOUND_HANDLES; i++) + if (_handles[i].type == kEffectHandle && _handles[i].resId == resId) { + debug(1, "Skipped playing SFX #%d", resId); + return; + } + SndHandle *handle = getHandle(); handle->type = kEffectHandle; + handle->resId = resId; playSoundBuffer(&handle->handle, buffer, 2 * volume, handle->type, loop); } @@ -129,6 +139,7 @@ void Sound::stopSound() { if (_handles[i].type == kEffectHandle) { _mixer->stopHandle(_handles[i].handle); _handles[i].type = kFreeHandle; + _handles[i].resId = -1; } } diff --git a/engines/saga/sound.h b/engines/saga/sound.h index 9cf8f29767..7ee2765a0f 100644 --- a/engines/saga/sound.h +++ b/engines/saga/sound.h @@ -63,6 +63,7 @@ enum sndHandleType { struct SndHandle { Audio::SoundHandle handle; sndHandleType type; + int resId; }; class Sound { @@ -71,7 +72,7 @@ public: Sound(SagaEngine *vm, Audio::Mixer *mixer); ~Sound(); - void playSound(SoundBuffer &buffer, int volume, bool loop); + void playSound(SoundBuffer &buffer, int volume, bool loop, int resId); void pauseSound(); void resumeSound(); void stopSound(); diff --git a/engines/saga/sthread.cpp b/engines/saga/sthread.cpp index c133f8de88..be674e5acd 100644 --- a/engines/saga/sthread.cpp +++ b/engines/saga/sthread.cpp @@ -58,6 +58,8 @@ ScriptThread &Script::createThread(uint16 scriptModuleNumber, uint16 scriptEntry _threadList.push_front(newThread); + debug(3, "createThread(). Total threads: %d", _threadList.size()); + ScriptThread &tmp = *_threadList.begin(); tmp._stackBuf = (int16 *)malloc(ScriptThread::THREAD_STACK_SIZE * sizeof(int16)); tmp._stackTopIndex = ScriptThread::THREAD_STACK_SIZE - 2; @@ -78,6 +80,8 @@ void Script::wakeUpActorThread(int waitType, void *threadObj) { void Script::wakeUpThreads(int waitType) { ScriptThreadList::iterator threadIterator; + debug(3, "wakeUpThreads(%d)", waitType); + for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) { ScriptThread &thread = *threadIterator; if ((thread._flags & kTFlagWaiting) && (thread._waitType == waitType)) { @@ -89,6 +93,8 @@ void Script::wakeUpThreads(int waitType) { void Script::wakeUpThreadsDelayed(int waitType, int sleepTime) { ScriptThreadList::iterator threadIterator; + debug(3, "wakeUpThreads(%d, %d)", waitType, sleepTime); + for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) { ScriptThread &thread = *threadIterator; if ((thread._flags & kTFlagWaiting) && (thread._waitType == waitType)) { @@ -169,6 +175,8 @@ void Script::executeThreads(uint msec) { void Script::abortAllThreads() { ScriptThreadList::iterator threadIterator; + debug(3, "abortAllThreads()"); + threadIterator = _threadList.begin(); while (threadIterator != _threadList.end()) { diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 814fbff636..33aa5514f2 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -31,23 +31,19 @@ #include "sci/event.h" #include "sci/resource.h" #include "sci/engine/state.h" +#include "sci/engine/kernel.h" #include "sci/engine/selector.h" #include "sci/engine/savegame.h" #include "sci/engine/gc.h" #include "sci/engine/features.h" -#ifdef USE_OLD_MUSIC_FUNCTIONS -#include "sci/sound/iterator/songlib.h" // for SongLibrary -#include "sci/sound/iterator/iterator.h" // for SCI_SONG_ITERATOR_TYPE_SCI0 -#else +#include "sci/sound/midiparser_sci.h" #include "sci/sound/music.h" -#endif #include "sci/sound/drivers/mididriver.h" -#include "sci/graphics/gui.h" -#include "sci/graphics/gui32.h" #include "sci/graphics/cursor.h" #include "sci/graphics/screen.h" #include "sci/graphics/paint.h" #include "sci/graphics/paint16.h" +#include "sci/graphics/paint32.h" #include "sci/graphics/palette.h" #include "sci/parser/vocabulary.h" @@ -70,15 +66,15 @@ bool g_debug_track_mouse_clicks = false; // Refer to the "addresses" command on how to pass address parameters static int parse_reg_t(EngineState *s, const char *str, reg_t *dest, bool mayBeValue); -Console::Console(SciEngine *engine) : GUI::Debugger() { - _engine = engine; +Console::Console(SciEngine *engine) : GUI::Debugger(), + _engine(engine), _debugState(engine->_debugState) { // Variables DVar_Register("sleeptime_factor", &g_debug_sleeptime_factor, DVAR_INT, 0); - DVar_Register("gc_interval", &engine->_gamestate->script_gc_interval, DVAR_INT, 0); + DVar_Register("gc_interval", &engine->_gamestate->scriptGCInterval, DVAR_INT, 0); DVar_Register("simulated_key", &g_debug_simulated_key, DVAR_INT, 0); DVar_Register("track_mouse_clicks", &g_debug_track_mouse_clicks, DVAR_BOOL, 0); - DVar_Register("script_abort_flag", &_engine->_gamestate->script_abort_flag, DVAR_INT, 0); + DVar_Register("script_abort_flag", &_engine->_gamestate->abortScriptProcessing, DVAR_INT, 0); // General DCmd_Register("help", WRAP_METHOD(Console, cmdHelp)); @@ -106,6 +102,7 @@ Console::Console(SciEngine *engine) : GUI::Debugger() { DCmd_Register("list", WRAP_METHOD(Console, cmdList)); DCmd_Register("hexgrep", WRAP_METHOD(Console, cmdHexgrep)); DCmd_Register("verify_scripts", WRAP_METHOD(Console, cmdVerifyScripts)); + DCmd_Register("show_instruments", WRAP_METHOD(Console, cmdShowInstruments)); // Game DCmd_Register("save_game", WRAP_METHOD(Console, cmdSaveGame)); DCmd_Register("restore_game", WRAP_METHOD(Console, cmdRestoreGame)); @@ -151,15 +148,17 @@ Console::Console(SciEngine *engine) : GUI::Debugger() { DCmd_Register("addresses", WRAP_METHOD(Console, cmdAddresses)); DCmd_Register("registers", WRAP_METHOD(Console, cmdRegisters)); DCmd_Register("dissect_script", WRAP_METHOD(Console, cmdDissectScript)); - DCmd_Register("set_acc", WRAP_METHOD(Console, cmdSetAccumulator)); DCmd_Register("backtrace", WRAP_METHOD(Console, cmdBacktrace)); DCmd_Register("bt", WRAP_METHOD(Console, cmdBacktrace)); // alias - DCmd_Register("step", WRAP_METHOD(Console, cmdStep)); - DCmd_Register("s", WRAP_METHOD(Console, cmdStep)); // alias + DCmd_Register("trace", WRAP_METHOD(Console, cmdTrace)); + DCmd_Register("t", WRAP_METHOD(Console, cmdTrace)); // alias + DCmd_Register("s", WRAP_METHOD(Console, cmdTrace)); // alias + DCmd_Register("stepover", WRAP_METHOD(Console, cmdStepOver)); + DCmd_Register("p", WRAP_METHOD(Console, cmdStepOver)); // alias + DCmd_Register("step_ret", WRAP_METHOD(Console, cmdStepRet)); + DCmd_Register("pret", WRAP_METHOD(Console, cmdStepRet)); // alias DCmd_Register("step_event", WRAP_METHOD(Console, cmdStepEvent)); DCmd_Register("se", WRAP_METHOD(Console, cmdStepEvent)); // alias - DCmd_Register("step_ret", WRAP_METHOD(Console, cmdStepRet)); - DCmd_Register("sret", WRAP_METHOD(Console, cmdStepRet)); // alias DCmd_Register("step_global", WRAP_METHOD(Console, cmdStepGlobal)); DCmd_Register("sg", WRAP_METHOD(Console, cmdStepGlobal)); // alias DCmd_Register("step_callk", WRAP_METHOD(Console, cmdStepCallk)); @@ -171,8 +170,10 @@ Console::Console(SciEngine *engine) : GUI::Debugger() { // Breakpoints DCmd_Register("bp_list", WRAP_METHOD(Console, cmdBreakpointList)); DCmd_Register("bplist", WRAP_METHOD(Console, cmdBreakpointList)); // alias + DCmd_Register("bl", WRAP_METHOD(Console, cmdBreakpointList)); // alias DCmd_Register("bp_del", WRAP_METHOD(Console, cmdBreakpointDelete)); DCmd_Register("bpdel", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias + DCmd_Register("bc", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias DCmd_Register("bp_exec_method", WRAP_METHOD(Console, cmdBreakpointExecMethod)); DCmd_Register("bpx", WRAP_METHOD(Console, cmdBreakpointExecMethod)); // alias DCmd_Register("bp_exec_function", WRAP_METHOD(Console, cmdBreakpointExecFunction)); @@ -180,48 +181,42 @@ Console::Console(SciEngine *engine) : GUI::Debugger() { // VM DCmd_Register("script_steps", WRAP_METHOD(Console, cmdScriptSteps)); DCmd_Register("vm_varlist", WRAP_METHOD(Console, cmdVMVarlist)); - DCmd_Register("vmvarlist", WRAP_METHOD(Console, cmdVMVarlist)); // alias + DCmd_Register("vmvarlist", WRAP_METHOD(Console, cmdVMVarlist)); // alias + DCmd_Register("vl", WRAP_METHOD(Console, cmdVMVarlist)); // alias DCmd_Register("vm_vars", WRAP_METHOD(Console, cmdVMVars)); - DCmd_Register("vmvars", WRAP_METHOD(Console, cmdVMVars)); // alias + DCmd_Register("vmvars", WRAP_METHOD(Console, cmdVMVars)); // alias + DCmd_Register("vv", WRAP_METHOD(Console, cmdVMVars)); // alias DCmd_Register("stack", WRAP_METHOD(Console, cmdStack)); DCmd_Register("value_type", WRAP_METHOD(Console, cmdValueType)); DCmd_Register("view_listnode", WRAP_METHOD(Console, cmdViewListNode)); DCmd_Register("view_reference", WRAP_METHOD(Console, cmdViewReference)); - DCmd_Register("vr", WRAP_METHOD(Console, cmdViewReference)); // alias + DCmd_Register("vr", WRAP_METHOD(Console, cmdViewReference)); // alias DCmd_Register("view_object", WRAP_METHOD(Console, cmdViewObject)); - DCmd_Register("vo", WRAP_METHOD(Console, cmdViewObject)); // alias + DCmd_Register("vo", WRAP_METHOD(Console, cmdViewObject)); // alias DCmd_Register("active_object", WRAP_METHOD(Console, cmdViewActiveObject)); DCmd_Register("acc_object", WRAP_METHOD(Console, cmdViewAccumulatorObject)); - g_debugState.seeking = kDebugSeekNothing; - g_debugState.seekLevel = 0; - g_debugState.runningStep = 0; - g_debugState.stopOnEvent = false; - g_debugState.debugging = false; - g_debugState.breakpointWasHit = false; - g_debugState._breakpoints.clear(); // No breakpoints defined - g_debugState._activeBreakpointTypes = 0; + _debugState.seeking = kDebugSeekNothing; + _debugState.seekLevel = 0; + _debugState.runningStep = 0; + _debugState.stopOnEvent = false; + _debugState.debugging = false; + _debugState.breakpointWasHit = false; + _debugState._breakpoints.clear(); // No breakpoints defined + _debugState._activeBreakpointTypes = 0; } Console::~Console() { } void Console::preEnter() { -#ifdef USE_OLD_MUSIC_FUNCTIONS - if (_engine->_gamestate) - _engine->_gamestate->_sound.sfx_suspend(true); -#endif - if (_engine->_gamestate && _engine->_gamestate->_soundCmd) - _engine->_gamestate->_soundCmd->pauseAll(true); + if (g_sci && g_sci->_soundCmd) + g_sci->_soundCmd->pauseAll(true); } void Console::postEnter() { -#ifdef USE_OLD_MUSIC_FUNCTIONS - if (_engine->_gamestate) - _engine->_gamestate->_sound.sfx_suspend(false); -#endif - if (_engine->_gamestate && _engine->_gamestate->_soundCmd) - _engine->_gamestate->_soundCmd->pauseAll(false); + if (g_sci && g_sci->_soundCmd) + g_sci->_soundCmd->pauseAll(false); if (!_videoFile.empty()) { _engine->_gfxCursor->kernelHide(); @@ -243,8 +238,9 @@ void Console::postEnter() { if (videoDecoder && videoDecoder->loadFile(_videoFile)) { uint16 x = (g_system->getWidth() - videoDecoder->getWidth()) / 2; uint16 y = (g_system->getHeight() - videoDecoder->getHeight()) / 2; + bool skipVideo = false; - while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo()) { + while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) { if (videoDecoder->needsUpdate()) { Graphics::Surface *frame = videoDecoder->decodeNextFrame(); if (frame) { @@ -258,8 +254,10 @@ void Console::postEnter() { } Common::Event event; - while (g_system->getEventManager()->pollEvent(event)) - ; + while (g_system->getEventManager()->pollEvent(event)) { + if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP) + skipVideo = true; + } g_system->delayMillis(10); } @@ -274,14 +272,6 @@ void Console::postEnter() { } } - -#if 0 -// Unused -#define LOOKUP_SPECIES(species) (\ - (species >= 1000) ? species : *(s->_classTable[species].scriptposp) \ - + s->_classTable[species].class_offset) -#endif - bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf("\n"); DebugPrintf("Variables\n"); @@ -326,6 +316,7 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf(" list - Lists all the resources of a given type\n"); DebugPrintf(" hexgrep - Searches some resources for a particular sequence of bytes, represented as hexadecimal numbers\n"); DebugPrintf(" verify_scripts - Performs sanity checks on SCI1.1-SCI2.1 game scripts (e.g. if they're up to 64KB in total)\n"); + DebugPrintf(" show_instruments - Shows the instruments of a specific song, or all songs\n"); DebugPrintf("\n"); DebugPrintf("Game:\n"); DebugPrintf(" save_game - Saves the current game state to the hard disk\n"); @@ -370,11 +361,11 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf(" addresses - Provides information on how to pass addresses\n"); DebugPrintf(" registers - Shows the current register values\n"); DebugPrintf(" dissect_script - Examines a script\n"); - DebugPrintf(" set_acc - Sets the accumulator\n"); DebugPrintf(" backtrace / bt - Dumps the send/self/super/call/calle/callb stack\n"); - DebugPrintf(" step / s - Executes one operation (no parameters) or several operations (specified as a parameter) \n"); + DebugPrintf(" trace / t / s - Executes one operation (no parameters) or several operations (specified as a parameter) \n"); + DebugPrintf(" stepover / p - Executes one operation, skips over call/send\n"); + DebugPrintf(" step_ret / pret - Steps forward until ret is called on the current execution stack level.\n"); DebugPrintf(" step_event / se - Steps forward until a SCI event is received.\n"); - DebugPrintf(" step_ret / sret - Steps forward until ret is called on the current execution stack level.\n"); DebugPrintf(" step_global / sg - Steps until the global variable with the specified index is modified.\n"); DebugPrintf(" step_callk / snk - Steps forward until it hits the next callk operation, or a specific callk (specified as a parameter)\n"); DebugPrintf(" disasm - Disassembles a method by name\n"); @@ -383,15 +374,15 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf(" go - Executes the script\n"); DebugPrintf("\n"); DebugPrintf("Breakpoints:\n"); - DebugPrintf(" bp_list / bplist - Lists the current breakpoints\n"); - DebugPrintf(" bp_del / bpdel - Deletes a breakpoint with the specified index\n"); + DebugPrintf(" bp_list / bplist / bl - Lists the current breakpoints\n"); + DebugPrintf(" bp_del / bpdel / bc - Deletes a breakpoint with the specified index\n"); DebugPrintf(" bp_exec_method / bpx - Sets a breakpoint on the execution of the specified method\n"); DebugPrintf(" bp_exec_function / bpe - Sets a breakpoint on the execution of the specified exported function\n"); DebugPrintf("\n"); DebugPrintf("VM:\n"); DebugPrintf(" script_steps - Shows the number of executed SCI operations\n"); - DebugPrintf(" vm_varlist / vmvarlist - Shows the addresses of variables in the VM\n"); - DebugPrintf(" vm_vars / vmvars - Displays or changes variables in the VM\n"); + DebugPrintf(" vm_varlist / vmvarlist / vl - Shows the addresses of variables in the VM\n"); + DebugPrintf(" vm_vars / vmvars / vv - Displays or changes variables in the VM\n"); DebugPrintf(" stack - Lists the specified number of stack elements\n"); DebugPrintf(" value_type - Determines the type of a value\n"); DebugPrintf(" view_listnode - Examines the list node at the given address\n"); @@ -414,19 +405,12 @@ ResourceType parseResourceType(const char *resid) { return res; } -const char *selector_name(EngineState *s, int selector) { - if (selector >= 0 && selector < (int)g_sci->getKernel()->getSelectorNamesSize()) - return g_sci->getKernel()->getSelectorName(selector).c_str(); - else - return "--INVALID--"; -} - bool Console::cmdGetVersion(int argc, const char **argv) { const char *viewTypeDesc[] = { "Unknown", "EGA", "VGA", "VGA SCI1.1", "Amiga" }; bool hasVocab997 = g_sci->getResMan()->testResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SELECTORS)) ? true : false; - DebugPrintf("Game ID: %s\n", _engine->getGameID()); + DebugPrintf("Game ID: %s\n", _engine->getGameIdStr()); DebugPrintf("Emulated interpreter version: %s\n", getSciVersionDesc(getSciVersion())); DebugPrintf("\n"); DebugPrintf("Detected features:\n"); @@ -434,9 +418,10 @@ bool Console::cmdGetVersion(int argc, const char **argv) { DebugPrintf("Sound type: %s\n", getSciVersionDesc(_engine->_features->detectDoSoundType())); DebugPrintf("Graphics functions type: %s\n", getSciVersionDesc(_engine->_features->detectGfxFunctionsType())); DebugPrintf("Lofs type: %s\n", getSciVersionDesc(_engine->_features->detectLofsType())); - DebugPrintf("Move count type: %s\n", (_engine->_features->detectMoveCountType() == kIncrementMoveCount) ? "increment" : "ignore"); + DebugPrintf("Move count type: %s\n", (_engine->_features->handleMoveCount()) ? "increment" : "ignore"); DebugPrintf("SetCursor type: %s\n", getSciVersionDesc(_engine->_features->detectSetCursorType())); DebugPrintf("View type: %s\n", viewTypeDesc[g_sci->getResMan()->getViewType()]); + DebugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette->isMerging() ? "yes" : "no"); DebugPrintf("Resource volume version: %s\n", g_sci->getResMan()->getVolVersionDesc()); DebugPrintf("Resource map version: %s\n", g_sci->getResMan()->getMapVersionDesc()); DebugPrintf("Contains selector vocabulary (vocab.997): %s\n", hasVocab997 ? "yes" : "no"); @@ -482,14 +467,14 @@ bool Console::cmdSelector(int argc, const char **argv) { return true; } - for (uint seeker = 0; seeker < _engine->getKernel()->getSelectorNamesSize(); seeker++) { - if (!scumm_stricmp(_engine->getKernel()->getSelectorName(seeker).c_str(), argv[1])) { - DebugPrintf("Selector %s found at %03x (%d)\n", _engine->getKernel()->getSelectorName(seeker).c_str(), seeker, seeker); - return true; - } + Common::String name = argv[1]; + int seeker = _engine->getKernel()->findSelector(name.c_str()); + if (seeker >= 0) { + DebugPrintf("Selector %s found at %03x (%d)\n", name.c_str(), seeker, seeker); + return true; } - DebugPrintf("Selector %s wasn't found\n", argv[1]); + DebugPrintf("Selector %s wasn't found\n", name.c_str()); return true; } @@ -597,7 +582,7 @@ bool Console::cmdSetParseNodes(int argc, const char **argv) { bool Console::cmdRegisters(int argc, const char **argv) { EngineState *s = _engine->_gamestate; DebugPrintf("Current register values:\n"); - DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(s->r_acc), PRINT_REG(s->r_prev), s->restAdjustCur); + DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(s->r_acc), PRINT_REG(s->r_prev), s->restAdjust); if (!s->_executionStack.empty()) { DebugPrintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n", @@ -820,7 +805,7 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) { } Common::List<ResourceId> *resources = _engine->getResMan()->listResources(kResourceTypeScript); - sort(resources->begin(), resources->end(), ResourceIdLess()); + Common::sort(resources->begin(), resources->end()); Common::List<ResourceId>::iterator itr = resources->begin(); DebugPrintf("%d SCI1.1-SCI2.1 scripts found, performing sanity checks...\n", resources->size()); @@ -829,15 +814,15 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) { while (itr != resources->end()) { script = _engine->getResMan()->findResource(*itr, false); if (!script) - DebugPrintf("Error: script %d couldn't be loaded\n", itr->number); + DebugPrintf("Error: script %d couldn't be loaded\n", itr->getNumber()); - heap = _engine->getResMan()->findResource(*itr, false); + heap = _engine->getResMan()->findResource(ResourceId(kResourceTypeHeap, itr->getNumber()), false); if (!heap) - DebugPrintf("Error: script %d doesn't have a corresponding heap\n", itr->number); + DebugPrintf("Error: script %d doesn't have a corresponding heap\n", itr->getNumber()); if (script && heap && (script->size + heap->size > 65535)) DebugPrintf("Error: script and heap %d together are larger than 64KB (%d bytes)\n", - itr->number, script->size + heap->size); + itr->getNumber(), script->size + heap->size); ++itr; } @@ -847,6 +832,167 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) { return true; } +bool Console::cmdShowInstruments(int argc, const char **argv) { + int songNumber = -1; + + if (argc == 2) + songNumber = atoi(argv[1]); + + SciVersion doSoundVersion = _engine->_features->detectDoSoundType(); + MidiPlayer *player = MidiPlayer_Midi_create(doSoundVersion); + MidiParser_SCI *parser = new MidiParser_SCI(doSoundVersion, 0); + parser->setMidiDriver(player); + + Common::List<ResourceId> *resources = _engine->getResMan()->listResources(kResourceTypeSound); + Common::sort(resources->begin(), resources->end()); + Common::List<ResourceId>::iterator itr = resources->begin(); + int instruments[128]; + bool instrumentsSongs[128][1000]; + + for (int i = 0; i < 128; i++) + instruments[i] = 0; + + for (int i = 0; i < 128; i++) + for (int j = 0; j < 1000; j++) + instrumentsSongs[i][j] = false; + + if (songNumber == -1) { + DebugPrintf("%d sounds found, checking their instrument mappings...\n", resources->size()); + DebugPrintf("Instruments:\n"); + DebugPrintf("============\n"); + } + + SoundResource *sound; + + while (itr != resources->end()) { + if (songNumber >= 0 && itr->getNumber() != songNumber) { + ++itr; + continue; + } + + sound = new SoundResource(itr->getNumber(), _engine->getResMan(), doSoundVersion); + int channelFilterMask = sound->getChannelFilterMask(player->getPlayId(), player->hasRhythmChannel()); + SoundResource::Track *track = sound->getTrackByType(player->getPlayId()); + if (track->digitalChannelNr != -1) { + // Skip digitized sound effects + delete sound; + ++itr; + continue; + } + + parser->loadMusic(track, NULL, channelFilterMask, doSoundVersion); + const byte *channelData = parser->getMixedData(); + + byte curEvent = 0, prevEvent = 0, command = 0; + bool endOfTrack = false; + bool firstOneShown = false; + + DebugPrintf("Song %d: ", itr->getNumber()); + + do { + while (*channelData == 0xF8) + channelData++; + + channelData++; // delta + + if ((*channelData & 0xF0) >= 0x80) + curEvent = *(channelData++); + else + curEvent = prevEvent; + if (curEvent < 0x80) + continue; + + prevEvent = curEvent; + command = curEvent >> 4; + + byte channel; + + switch (command) { + case 0xC: // program change + channel = curEvent & 0x0F; + if (channel != 15) { // SCI special + byte instrument = *channelData++; + if (!firstOneShown) + firstOneShown = true; + else + DebugPrintf(","); + + DebugPrintf(" %d", instrument); + instruments[instrument]++; + instrumentsSongs[instrument][itr->getNumber()] = true; + } + break; + case 0xD: + channelData++; // param1 + break; + case 0xB: + channelData++; // param1 + channelData++; // param2 + break; + case 0x8: + case 0x9: + case 0xA: + case 0xE: + channelData++; // param1 + channelData++; // param2 + break; + case 0xF: + if ((curEvent & 0x0F) == 0x2) { + channelData++; // param1 + channelData++; // param2 + } else if ((curEvent & 0x0F) == 0x3) { + channelData++; // param1 + } else if ((curEvent & 0x0F) == 0xF) { // META + byte type = *channelData++; + if (type == 0x2F) {// end of track reached + endOfTrack = true; + } else { + // no further processing necessary + } + } + break; + default: + break; + } + } while (!endOfTrack); + + DebugPrintf("\n"); + + delete sound; + ++itr; + } + + delete parser; + delete player; + + DebugPrintf("\n"); + + if (songNumber == -1) { + DebugPrintf("Used instruments: "); + for (int i = 0; i < 128; i++) { + if (instruments[i] > 0) + DebugPrintf("%d, ", i); + } + DebugPrintf("\n\n"); + + DebugPrintf("Used instruments in songs:\n"); + for (int i = 0; i < 128; i++) { + if (instruments[i] > 0) { + DebugPrintf("Instrument %d: ", i); + for (int j = 0; j < 1000; j++) { + if (instrumentsSongs[i][j]) + DebugPrintf("%d, ", j); + } + DebugPrintf("\n"); + } + } + + DebugPrintf("\n\n"); + } + + return true; +} + bool Console::cmdList(int argc, const char **argv) { if (argc < 2) { DebugPrintf("Lists all the resources of a given type\n"); @@ -870,19 +1016,19 @@ bool Console::cmdList(int argc, const char **argv) { } Common::List<ResourceId> *resources = _engine->getResMan()->listResources(res, number); - sort(resources->begin(), resources->end(), ResourceIdLess()); + Common::sort(resources->begin(), resources->end()); Common::List<ResourceId>::iterator itr = resources->begin(); int cnt = 0; while (itr != resources->end()) { if (number == -1) { - DebugPrintf("%8i", itr->number); + DebugPrintf("%8i", itr->getNumber()); if (++cnt % 10 == 0) DebugPrintf("\n"); - } - else if (number == (int)itr->number) { - DebugPrintf("(%3i, %3i, %3i, %3i) ", (itr->tuple >> 24) & 0xff, (itr->tuple >> 16) & 0xff, - (itr->tuple >> 8) & 0xff, itr->tuple & 0xff); + } else if (number == (int)itr->getNumber()) { + const uint32 tuple = itr->getTuple(); + DebugPrintf("(%3i, %3i, %3i, %3i) ", (tuple >> 24) & 0xff, (tuple >> 16) & 0xff, + (tuple >> 8) & 0xff, tuple & 0xff); if (++cnt % 4 == 0) DebugPrintf("\n"); } @@ -920,7 +1066,7 @@ bool Console::cmdSaveGame(int argc, const char **argv) { } // TODO: enable custom descriptions? force filename into a specific format? - if (gamestate_save(_engine->_gamestate, out, "debugging", version)) { + if (!gamestate_save(_engine->_gamestate, out, "debugging", version)) { DebugPrintf("Saving the game state to '%s' failed\n", argv[1]); } else { out->finalize(); @@ -957,8 +1103,7 @@ bool Console::cmdRestoreGame(int argc, const char **argv) { } bool Console::cmdRestartGame(int argc, const char **argv) { - _engine->_gamestate->restarting_flags |= SCI_GAME_IS_RESTARTING_NOW; - _engine->_gamestate->script_abort_flag = 1; + _engine->_gamestate->abortScriptProcessing = kAbortRestartGame;; return false; } @@ -1135,7 +1280,11 @@ bool Console::cmdDrawRobot(int argc, const char **argv) { uint16 resourceId = atoi(argv[1]); - _engine->_gui32->drawRobot(resourceId); + if (_engine->_gfxPaint32) { + _engine->_gfxPaint32->debugDrawRobot(resourceId); + } else { + DebugPrintf("command not available in non-sci32 games"); + } return true; } #endif @@ -1217,7 +1366,7 @@ bool Console::cmdPrintSegmentTable(int argc, const char **argv) { switch (mobj->getType()) { case SEG_TYPE_SCRIPT: - DebugPrintf("S script.%03d l:%d ", (*(Script *)mobj)._nr, (*(Script *)mobj).getLockers()); + DebugPrintf("S script.%03d l:%d ", (*(Script *)mobj).getScriptNumber(), (*(Script *)mobj).getLockers()); break; case SEG_TYPE_CLONES: @@ -1252,10 +1401,16 @@ bool Console::cmdPrintSegmentTable(int argc, const char **argv) { DebugPrintf("M dynmem: %d bytes", (*(DynMem *)mobj)._size); break; - case SEG_TYPE_STRING_FRAG: - DebugPrintf("F string fragments"); +#ifdef ENABLE_SCI32 + case SEG_TYPE_ARRAY: + DebugPrintf("A SCI32 arrays (%d)", (*(ArrayTable *)mobj).entries_used); break; + case SEG_TYPE_STRING: + DebugPrintf("T SCI32 strings (%d)", (*(StringTable *)mobj).entries_used); + break; +#endif + default: DebugPrintf("I Invalid (type = %x)", mobj->getType()); break; @@ -1281,9 +1436,9 @@ bool Console::segmentInfo(int nr) { case SEG_TYPE_SCRIPT: { Script *scr = (Script *)mobj; - DebugPrintf("script.%03d locked by %d, bufsize=%d (%x)\n", scr->_nr, scr->getLockers(), (uint)scr->getBufSize(), (uint)scr->getBufSize()); + DebugPrintf("script.%03d locked by %d, bufsize=%d (%x)\n", scr->getScriptNumber(), scr->getLockers(), (uint)scr->getBufSize(), (uint)scr->getBufSize()); if (scr->getExportTable()) - DebugPrintf(" Exports: %4d at %d\n", scr->getExportsNr(), (int)(((const byte *)scr->getExportTable()) - ((const byte *)scr->_buf))); + DebugPrintf(" Exports: %4d at %d\n", scr->getExportsNr(), (int)(((const byte *)scr->getExportTable()) - ((const byte *)scr->getBuf()))); else DebugPrintf(" Exports: none\n"); @@ -1394,10 +1549,14 @@ bool Console::segmentInfo(int nr) { } break; - case SEG_TYPE_STRING_FRAG: { - DebugPrintf("string frags\n"); +#ifdef ENABLE_SCI32 + case SEG_TYPE_STRING: + DebugPrintf("SCI32 strings\n"); break; - } + case SEG_TYPE_ARRAY: + DebugPrintf("SCI32 arrays\n"); + break; +#endif default : DebugPrintf("Invalid type %d\n", mobj->getType()); @@ -1413,7 +1572,7 @@ bool Console::cmdSegmentInfo(int argc, const char **argv) { DebugPrintf("Provides information on the specified segment(s)\n"); DebugPrintf("Usage: %s <segment number>\n", argv[0]); DebugPrintf("<segment number> can be a number, which shows the information of the segment with\n"); - DebugPrintf("the specified number, or \"all\" to show information on all active segments"); + DebugPrintf("the specified number, or \"all\" to show information on all active segments\n"); return true; } @@ -1421,9 +1580,11 @@ bool Console::cmdSegmentInfo(int argc, const char **argv) { for (uint i = 0; i < _engine->_gamestate->_segMan->_heap.size(); i++) segmentInfo(i); } else { - int nr = atoi(argv[1]); - if (!segmentInfo(nr)) - DebugPrintf("Segment %04x does not exist\n", nr); + int segmentNr; + if (!parseInteger(argv[1], segmentNr)) + return true; + if (!segmentInfo(segmentNr)) + DebugPrintf("Segment %04xh does not exist\n", segmentNr); } return true; @@ -1436,21 +1597,23 @@ bool Console::cmdKillSegment(int argc, const char **argv) { DebugPrintf("Usage: %s <segment number>\n", argv[0]); return true; } - - _engine->_gamestate->_segMan->getScript(atoi(argv[1]))->setLockers(0); + int segmentNumber; + if (!parseInteger(argv[1], segmentNumber)) + return true; + _engine->_gamestate->_segMan->getScript(segmentNumber)->setLockers(0); return true; } bool Console::cmdShowMap(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Shows one of the screen maps\n"); + DebugPrintf("Switches to one of the following screen maps\n"); DebugPrintf("Usage: %s <screen map>\n", argv[0]); DebugPrintf("Screen maps:\n"); - DebugPrintf("- 0: visual map (back buffer)\n"); - DebugPrintf("- 1: priority map (back buffer)\n"); - DebugPrintf("- 2: control map (static buffer)\n"); - DebugPrintf("- 3: display screen (newgui only)\n"); + DebugPrintf("- 0: visual map\n"); + DebugPrintf("- 1: priority map\n"); + DebugPrintf("- 2: control map\n"); + DebugPrintf("- 3: display screen\n"); return true; } @@ -1473,23 +1636,7 @@ bool Console::cmdShowMap(int argc, const char **argv) { bool Console::cmdSongLib(int argc, const char **argv) { DebugPrintf("Song library:\n"); - -#ifdef USE_OLD_MUSIC_FUNCTIONS - Song *seeker = _engine->_gamestate->_sound._songlib._lib; - - do { - DebugPrintf(" %p", (void *)seeker); - - if (seeker) { - DebugPrintf("[%04lx,p=%d,s=%d]->", seeker->_handle, seeker->_priority, seeker->_status); - seeker = seeker->_next; - } - DebugPrintf("\n"); - } while (seeker); - DebugPrintf("\n"); -#else - _engine->_gamestate->_soundCmd->printPlayList(this); -#endif + g_sci->_soundCmd->printPlayList(this); return true; } @@ -1509,7 +1656,7 @@ bool Console::cmdSongInfo(int argc, const char **argv) { return true; } - _engine->_gamestate->_soundCmd->printSongInfo(addr, this); + g_sci->_soundCmd->printSongInfo(addr, this); return true; } @@ -1528,7 +1675,7 @@ bool Console::cmdStartSound(int argc, const char **argv) { return true; } - _engine->_gamestate->_soundCmd->startNewSound(number); + g_sci->_soundCmd->startNewSound(number); return false; } @@ -1552,37 +1699,21 @@ bool Console::cmdToggleSound(int argc, const char **argv) { return true; } -#ifdef USE_OLD_MUSIC_FUNCTIONS - int handle = id.segment << 16 | id.offset; // frobnicate handle - - if (id.segment) { - SegManager *segMan = _engine->_gamestate->_segMan; // for writeSelectorValue - _engine->_gamestate->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED); - _engine->_gamestate->_sound.sfx_remove_song(handle); - writeSelectorValue(segMan, id, SELECTOR(signal), SIGNAL_OFFSET); - writeSelectorValue(segMan, id, SELECTOR(nodePtr), 0); - writeSelectorValue(segMan, id, SELECTOR(handle), 0); - } -#else - Common::String newState = argv[2]; newState.toLowercase(); if (newState == "play") - _engine->_gamestate->_soundCmd->playSound(id); + g_sci->_soundCmd->processPlaySound(id); else if (newState == "stop") - _engine->_gamestate->_soundCmd->stopSound(id); + g_sci->_soundCmd->processStopSound(id, false); else DebugPrintf("New state can either be 'play' or 'stop'"); -#endif return true; } bool Console::cmdStopAllSounds(int argc, const char **argv) { -#ifndef USE_OLD_MUSIC_FUNCTIONS - _engine->_gamestate->_soundCmd->stopAllSounds(); -#endif + g_sci->_soundCmd->stopAllSounds(); DebugPrintf("All sounds have been stopped\n"); return true; @@ -1596,36 +1727,6 @@ bool Console::cmdIsSample(int argc, const char **argv) { return true; } -#ifdef USE_OLD_MUSIC_FUNCTIONS - Resource *song = _engine->getResMan()->findResource(ResourceId(kResourceTypeSound, atoi(argv[1])), 0); - SongIterator *songit; - Audio::AudioStream *data; - - if (!song) { - DebugPrintf("Not a sound resource!\n"); - return true; - } - - songit = songit_new(song->data, song->size, SCI_SONG_ITERATOR_TYPE_SCI0, 0xcaffe /* What do I care about the ID? */); - - if (!songit) { - DebugPrintf("Could not convert to song iterator!\n"); - return true; - } - - data = songit->getAudioStream(); - if (data) { - // TODO -/* - DebugPrintf("\nIs sample (encoding %dHz/%s/%04x)", data->conf.rate, (data->conf.stereo) ? - ((data->conf.stereo == SFX_PCM_STEREO_LR) ? "stereo-LR" : "stereo-RL") : "mono", data->conf.format); -*/ - delete data; - } else - DebugPrintf("Valid song, but not a sample.\n"); - - delete songit; -#else int16 number = atoi(argv[1]); if (!_engine->getResMan()->testResource(ResourceId(kResourceTypeSound, number))) { @@ -1649,7 +1750,6 @@ bool Console::cmdIsSample(int argc, const char **argv) { DebugPrintf("Sample size: %d, sample rate: %d, channels: %d, digital channel number: %d\n", track->digitalSampleSize, track->digitalSampleRate, track->channelCount, track->digitalChannelNr); -#endif return true; } @@ -1661,10 +1761,10 @@ bool Console::cmdGCInvoke(int argc, const char **argv) { } bool Console::cmdGCObjects(int argc, const char **argv) { - reg_t_hash_map *use_map = find_all_used_references(_engine->_gamestate); + AddrSet *use_map = findAllActiveReferences(_engine->_gamestate); DebugPrintf("Reachable object references (normalised):\n"); - for (reg_t_hash_map::iterator i = use_map->begin(); i != use_map->end(); ++i) { + for (AddrSet::iterator i = use_map->begin(); i != use_map->end(); ++i) { DebugPrintf(" - %04x:%04x\n", PRINT_REG(i->_key)); } @@ -1673,11 +1773,6 @@ bool Console::cmdGCObjects(int argc, const char **argv) { return true; } -void _print_address(void * _, reg_t addr) { - if (addr.segment) - g_sci->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(addr)); -} - bool Console::cmdGCShowReachable(int argc, const char **argv) { if (argc != 2) { DebugPrintf("Prints all addresses directly reachable from the memory object specified as parameter.\n"); @@ -1701,7 +1796,10 @@ bool Console::cmdGCShowReachable(int argc, const char **argv) { } DebugPrintf("Reachable from %04x:%04x:\n", PRINT_REG(addr)); - mobj->listAllOutgoingReferences(addr, NULL, _print_address); + const Common::Array<reg_t> tmp = mobj->listAllOutgoingReferences(addr); + for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) + if (it->segment) + g_sci->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(*it)); return true; } @@ -1730,7 +1828,10 @@ bool Console::cmdGCShowFreeable(int argc, const char **argv) { } DebugPrintf("Freeable in segment %04x:\n", addr.segment); - mobj->listAllDeallocatable(addr.segment, NULL, _print_address); + const Common::Array<reg_t> tmp = mobj->listAllDeallocatable(addr.segment); + for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) + if (it->segment) + g_sci->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(*it)); return true; } @@ -1772,9 +1873,9 @@ bool Console::cmdVMVarlist(int argc, const char **argv) { DebugPrintf("Addresses of variables in the VM:\n"); for (int i = 0; i < 4; i++) { - DebugPrintf("%s vars at %04x:%04x ", varnames[i], PRINT_REG(make_reg(s->variables_seg[i], s->variables[i] - s->variables_base[i]))); - if (s->variables_max) - DebugPrintf(" total %d", s->variables_max[i]); + DebugPrintf("%s vars at %04x:%04x ", varnames[i], PRINT_REG(make_reg(s->variablesSegment[i], s->variables[i] - s->variablesBase[i]))); + if (s->variablesMax) + DebugPrintf(" total %d", s->variablesMax[i]); DebugPrintf("\n"); } @@ -1782,76 +1883,95 @@ bool Console::cmdVMVarlist(int argc, const char **argv) { } bool Console::cmdVMVars(int argc, const char **argv) { - if (argc < 3) { + if (argc < 2) { DebugPrintf("Displays or changes variables in the VM\n"); DebugPrintf("Usage: %s <type> <varnum> [<value>]\n", argv[0]); - DebugPrintf("First parameter is either g(lobal), l(ocal), t(emp) or p(aram).\n"); - DebugPrintf("Second parameter is the var number\n"); + DebugPrintf("First parameter is either g(lobal), l(ocal), t(emp), p(aram) or a(cc).\n"); + DebugPrintf("Second parameter is the var number (not specified on acc)\n"); DebugPrintf("Third parameter (if specified) is the value to set the variable to, in address form\n"); DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } EngineState *s = _engine->_gamestate; - const char *varnames[] = {"global", "local", "temp", "param"}; - const char *varabbrev = "gltp"; - const char *vartype_pre = strchr(varabbrev, *argv[1]); - int vartype; - int idx; - - if (!vartype_pre) { + const char *varNames[] = {"global", "local", "temp", "param", "acc"}; + const char *varAbbrev = "gltpa"; + const char *varType_pre = strchr(varAbbrev, *argv[1]); + int varType; + int varIndex = 0; + reg_t *curValue = NULL; + const char *setValue = NULL; + + if (!varType_pre) { DebugPrintf("Invalid variable type '%c'\n", *argv[1]); return true; } - vartype = vartype_pre - varabbrev; + varType = varType_pre - varAbbrev; - char *endPtr = 0; - int idxLen = strlen(argv[2]); - const char *lastChar = argv[2] + idxLen - (idxLen == 0 ? 0 : 1); + switch (varType) { + case 0: + case 1: + case 2: + case 3: { + // for global, local, temp and param, we need an index + if (argc < 3) { + DebugPrintf("Variable number must be specified for requested type\n"); + return true; + } + if (argc > 4) { + DebugPrintf("Too many arguments\n"); + return true; + } - if ((strncmp(argv[2], "0x", 2) == 0) || (*lastChar == 'h')) { - // hexadecimal number - idx = strtol(argv[2], &endPtr, 16); - if ((*endPtr != 0) && (*endPtr != 'h')) { - DebugPrintf("Invalid hexadecimal index '%s'\n", argv[2]); + if (!parseInteger(argv[2], varIndex)) + return true; + + if (varIndex < 0) { + DebugPrintf("Variable number may not be negative\n"); return true; } - } else { - // decimal number - idx = strtol(argv[2], &endPtr, 10); - if (*endPtr != 0) { - DebugPrintf("Invalid decimal index '%s'\n", argv[2]); + + if ((s->variablesMax) && (s->variablesMax[varType] <= varIndex)) { + DebugPrintf("Maximum variable number for this type is %d (0x%x)\n", s->variablesMax[varType], s->variablesMax[varType]); return true; } + curValue = &s->variables[varType][varIndex]; + if (argc == 4) + setValue = argv[3]; + break; } - if (idx < 0) { - DebugPrintf("Invalid: negative index\n"); - return true; - } + case 4: + // acc + if (argc > 3) { + DebugPrintf("Too many arguments\n"); + return true; + } + curValue = &s->r_acc; + if (argc == 3) + setValue = argv[2]; + break; - if ((s->variables_max) && (s->variables_max[vartype] <= idx)) { - DebugPrintf("Max. index is %d (0x%x)\n", s->variables_max[vartype], s->variables_max[vartype]); - return true; + default: + break; } - switch (argc) { - case 3: - DebugPrintf("%s var %d == %04x:%04x\n", varnames[vartype], idx, PRINT_REG(s->variables[vartype][idx])); - break; - case 4: - if (parse_reg_t(_engine->_gamestate, argv[3], &s->variables[vartype][idx], true)) { + if (!setValue) { + if (varType == 4) + DebugPrintf("%s == %04x:%04x", varNames[varType], PRINT_REG(*curValue)); + else + DebugPrintf("%s var %d == %04x:%04x", varNames[varType], varIndex, PRINT_REG(*curValue)); + printBasicVarInfo(*curValue); + DebugPrintf("\n"); + } else { + if (parse_reg_t(s, setValue, curValue, true)) { DebugPrintf("Invalid value/address passed.\n"); DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); DebugPrintf("Or pass a decimal or hexadecimal value directly (e.g. 12, 1Ah)\n"); return true; } - break; - default: - DebugPrintf("Too many arguments\n"); } - return true; } @@ -1901,20 +2021,22 @@ bool Console::cmdValueType(int argc, const char **argv) { int t = g_sci->getKernel()->findRegType(val); switch (t) { - case KSIG_LIST: + case SIG_TYPE_LIST: DebugPrintf("List"); break; - case KSIG_OBJECT: + case SIG_TYPE_OBJECT: DebugPrintf("Object"); break; - case KSIG_REF: + case SIG_TYPE_REFERENCE: DebugPrintf("Reference"); break; - case KSIG_ARITHMETIC: - DebugPrintf("Arithmetic"); + case SIG_TYPE_INTEGER: + DebugPrintf("Integer"); + case SIG_TYPE_INTEGER | SIG_TYPE_NULL: + DebugPrintf("Null"); break; default: - DebugPrintf("Erroneous unknown type %02x(%d decimal)\n", t, t); + DebugPrintf("Erroneous unknown type 0x%02x (%d decimal)\n", t, t); } return true; @@ -1978,7 +2100,7 @@ bool Console::cmdViewReference(int argc, const char **argv) { return true; } - if (reg_end.segment != reg.segment) { + if (reg_end.segment != reg.segment && reg_end != NULL_REG) { DebugPrintf("Ending segment different from starting segment. Assuming no bound on dump.\n"); reg_end = NULL_REG; } @@ -1994,47 +2116,68 @@ bool Console::cmdViewReference(int argc, const char **argv) { switch (type) { case 0: break; - case KSIG_LIST: { - List *l = _engine->_gamestate->_segMan->lookupList(reg); + case SIG_TYPE_LIST: { + List *list = _engine->_gamestate->_segMan->lookupList(reg); DebugPrintf("list\n"); - if (l) - printList(l); + if (list) + printList(list); else DebugPrintf("Invalid list.\n"); } break; - case KSIG_NODE: + case SIG_TYPE_NODE: DebugPrintf("list node\n"); printNode(reg); break; - case KSIG_OBJECT: + case SIG_TYPE_OBJECT: DebugPrintf("object\n"); printObject(reg); break; - case KSIG_REF: { - int size; - const SegmentRef block = _engine->_gamestate->_segMan->dereference(reg); - size = block.maxSize; + case SIG_TYPE_REFERENCE: { + switch (_engine->_gamestate->_segMan->getSegmentType(reg.segment)) { +#ifdef ENABLE_SCI32 + case SEG_TYPE_STRING: { + DebugPrintf("SCI32 string\n"); + const SciString *str = _engine->_gamestate->_segMan->lookupString(reg); + Common::hexdump((const byte *) str->getRawData(), str->getSize(), 16, 0); + break; + } + case SEG_TYPE_ARRAY: { + DebugPrintf("SCI32 array:\n"); + const SciArray<reg_t> *array = _engine->_gamestate->_segMan->lookupArray(reg); + hexDumpReg(array->getRawData(), array->getSize(), 4, 0, true); + break; + } +#endif + default: { + int size; + const SegmentRef block = _engine->_gamestate->_segMan->dereference(reg); + size = block.maxSize; - DebugPrintf("raw data\n"); + DebugPrintf("raw data\n"); - if (reg_end.segment != 0 && size < reg_end.offset - reg.offset) { - DebugPrintf("Block end out of bounds (size %d). Resetting.\n", size); - reg_end = NULL_REG; - } + if (reg_end.segment != 0 && size < reg_end.offset - reg.offset) { + DebugPrintf("Block end out of bounds (size %d). Resetting.\n", size); + reg_end = NULL_REG; + } - if (reg_end.segment != 0 && (size >= reg_end.offset - reg.offset)) - size = reg_end.offset - reg.offset; + if (reg_end.segment != 0 && (size >= reg_end.offset - reg.offset)) + size = reg_end.offset - reg.offset; - if (reg_end.segment != 0) - DebugPrintf("Block size less than or equal to %d\n", size); + if (reg_end.segment != 0) + DebugPrintf("Block size less than or equal to %d\n", size); - Common::hexdump(block.raw, size, 16, 0); + if (block.isRaw) + Common::hexdump(block.raw, size, 16, 0); + else + hexDumpReg(block.reg, size / 2, 4, 0); + } } break; - case KSIG_ARITHMETIC: + } + case SIG_TYPE_INTEGER: DebugPrintf("arithmetic value\n %d (%04x)\n", (int16) reg.offset, reg.offset); break; default: @@ -2087,35 +2230,12 @@ bool Console::cmdViewAccumulatorObject(int argc, const char **argv) { } bool Console::cmdScriptSteps(int argc, const char **argv) { - DebugPrintf("Number of executed SCI operations: %d\n", _engine->_gamestate->script_step_counter); - return true; -} - -bool Console::cmdSetAccumulator(int argc, const char **argv) { - if (argc != 2) { - DebugPrintf("Sets the accumulator.\n"); - DebugPrintf("Usage: %s <address>\n", argv[0]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); - return true; - } - - reg_t val; - - if (parse_reg_t(_engine->_gamestate, argv[1], &val, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); - return true; - } - - _engine->_gamestate->r_acc = val; - + DebugPrintf("Number of executed SCI operations: %d\n", _engine->_gamestate->scriptStepCounter); return true; } bool Console::cmdBacktrace(int argc, const char **argv) { - DebugPrintf("Dumping the send/self/super/call/calle/callb stack:\n"); - - DebugPrintf("Call stack (current base: 0x%x):\n", _engine->_gamestate->execution_stack_base); + DebugPrintf("Call stack (current base: 0x%x):\n", _engine->_gamestate->executionStackBase); Common::List<ExecStack>::iterator iter; uint i = 0; @@ -2126,20 +2246,25 @@ bool Console::cmdBacktrace(int argc, const char **argv) { int paramc, totalparamc; switch (call.type) { - - case EXEC_STACK_TYPE_CALL: {// Normal function - DebugPrintf(" %x:[%x] %s::%s(", i, call.origin, objname, (call.selector == -1) ? "<call[be]?>" : - selector_name(_engine->_gamestate, call.selector)); - } - break; + case EXEC_STACK_TYPE_CALL: // Normal function + if (call.type == EXEC_STACK_TYPE_CALL) + DebugPrintf(" %x: script %d - ", i, (*(Script *)_engine->_gamestate->_segMan->_heap[call.addr.pc.segment]).getScriptNumber()); + if (call.debugSelector != -1) { + DebugPrintf("%s::%s(", objname, _engine->getKernel()->getSelectorName(call.debugSelector).c_str()); + } else if (call.debugExportId != -1) { + DebugPrintf("export %d (", call.debugExportId); + } else if (call.debugLocalCallOffset != -1) { + DebugPrintf("call %x (", call.debugLocalCallOffset); + } + break; case EXEC_STACK_TYPE_KERNEL: // Kernel function - DebugPrintf(" %x:[%x] k%s(", i, call.origin, _engine->getKernel()->getKernelName(call.selector).c_str()); + DebugPrintf(" %x:[%x] k%s(", i, call.debugOrigin, _engine->getKernel()->getKernelName(call.debugSelector).c_str()); break; case EXEC_STACK_TYPE_VARSELECTOR: - DebugPrintf(" %x:[%x] vs%s %s::%s (", i, call.origin, (call.argc) ? "write" : "read", - objname, _engine->getKernel()->getSelectorName(call.selector).c_str()); + DebugPrintf(" %x:[%x] vs%s %s::%s (", i, call.debugOrigin, (call.argc) ? "write" : "read", + objname, _engine->getKernel()->getSelectorName(call.debugSelector).c_str()); break; } @@ -2158,7 +2283,10 @@ bool Console::cmdBacktrace(int argc, const char **argv) { if (call.argc > 16) DebugPrintf("..."); - DebugPrintf(")\n obj@%04x:%04x", PRINT_REG(call.objp)); + DebugPrintf(")\n "); + if (call.debugOrigin != -1) + DebugPrintf("by %x ", call.debugOrigin); + DebugPrintf("obj@%04x:%04x", PRINT_REG(call.objp)); if (call.type == EXEC_STACK_TYPE_CALL) { DebugPrintf(" pc=%04x:%04x", PRINT_REG(call.addr.pc)); if (call.sp == CALL_SP_CARRY) @@ -2171,33 +2299,39 @@ bool Console::cmdBacktrace(int argc, const char **argv) { DebugPrintf(" pc:none"); DebugPrintf(" argp:ST:%04x", (unsigned)(call.variables_argp - _engine->_gamestate->stack_base)); - if (call.type == EXEC_STACK_TYPE_CALL) - DebugPrintf(" script: %d", (*(Script *)_engine->_gamestate->_segMan->_heap[call.addr.pc.segment])._nr); DebugPrintf("\n"); } return true; } -bool Console::cmdStep(int argc, const char **argv) { +bool Console::cmdTrace(int argc, const char **argv) { if (argc == 2 && atoi(argv[1]) > 0) - g_debugState.runningStep = atoi(argv[1]) - 1; - g_debugState.debugging = true; + _debugState.runningStep = atoi(argv[1]) - 1; + _debugState.debugging = true; + + return false; +} + +bool Console::cmdStepOver(int argc, const char **argv) { + _debugState.seeking = kDebugSeekStepOver; + _debugState.seekLevel = _engine->_gamestate->_executionStack.size(); + _debugState.debugging = true; return false; } bool Console::cmdStepEvent(int argc, const char **argv) { - g_debugState.stopOnEvent = true; - g_debugState.debugging = true; + _debugState.stopOnEvent = true; + _debugState.debugging = true; return false; } bool Console::cmdStepRet(int argc, const char **argv) { - g_debugState.seeking = kDebugSeekLevelRet; - g_debugState.seekLevel = _engine->_gamestate->_executionStack.size() - 1; - g_debugState.debugging = true; + _debugState.seeking = kDebugSeekLevelRet; + _debugState.seekLevel = _engine->_gamestate->_executionStack.size() - 1; + _debugState.debugging = true; return false; } @@ -2209,9 +2343,9 @@ bool Console::cmdStepGlobal(int argc, const char **argv) { return true; } - g_debugState.seeking = kDebugSeekGlobal; - g_debugState.seekSpecial = atoi(argv[1]); - g_debugState.debugging = true; + _debugState.seeking = kDebugSeekGlobal; + _debugState.seekSpecial = atoi(argv[1]); + _debugState.debugging = true; return false; } @@ -2239,12 +2373,12 @@ bool Console::cmdStepCallk(int argc, const char **argv) { } } - g_debugState.seeking = kDebugSeekSpecialCallk; - g_debugState.seekSpecial = callk_index; + _debugState.seeking = kDebugSeekSpecialCallk; + _debugState.seekSpecial = callk_index; } else { - g_debugState.seeking = kDebugSeekCallk; + _debugState.seeking = kDebugSeekCallk; } - g_debugState.debugging = true; + _debugState.debugging = true; return false; } @@ -2357,11 +2491,11 @@ bool Console::cmdSend(int argc, const char **argv) { return true; } - const char *selector_name = argv[2]; - int selectorId = _engine->getKernel()->findSelector(selector_name); + const char *selectorName = argv[2]; + int selectorId = _engine->getKernel()->findSelector(selectorName); if (selectorId < 0) { - DebugPrintf("Unknown selector: \"%s\"\n", selector_name); + DebugPrintf("Unknown selector: \"%s\"\n", selectorName); return true; } @@ -2371,10 +2505,10 @@ bool Console::cmdSend(int argc, const char **argv) { return true; } - SelectorType selector_type = lookupSelector(_engine->_gamestate->_segMan, object, selectorId, 0, 0); + SelectorType selector_type = lookupSelector(_engine->_gamestate->_segMan, object, selectorId, NULL, NULL); if (selector_type == kSelectorNone) { - DebugPrintf("Object does not support selector: \"%s\"\n", selector_name); + DebugPrintf("Object does not support selector: \"%s\"\n", selectorName); return true; } @@ -2426,7 +2560,7 @@ bool Console::cmdSend(int argc, const char **argv) { bool Console::cmdGo(int argc, const char **argv) { // CHECKME: is this necessary? - g_debugState.seeking = kDebugSeekNothing; + _debugState.seeking = kDebugSeekNothing; return Cmd_Exit(argc, argv); } @@ -2437,8 +2571,8 @@ bool Console::cmdBreakpointList(int argc, const char **argv) { DebugPrintf("Breakpoint list:\n"); - Common::List<Breakpoint>::const_iterator bp = g_debugState._breakpoints.begin(); - Common::List<Breakpoint>::const_iterator end = g_debugState._breakpoints.end(); + Common::List<Breakpoint>::const_iterator bp = _debugState._breakpoints.begin(); + Common::List<Breakpoint>::const_iterator end = _debugState._breakpoints.end(); for (; bp != end; ++bp) { DebugPrintf(" #%i: ", i); switch (bp->type) { @@ -2454,6 +2588,9 @@ bool Console::cmdBreakpointList(int argc, const char **argv) { i++; } + if (!i) + DebugPrintf(" No breakpoints defined.\n"); + return true; } @@ -2461,14 +2598,21 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) { if (argc != 2) { DebugPrintf("Deletes a breakpoint with the specified index.\n"); DebugPrintf("Usage: %s <breakpoint index>\n", argv[0]); + DebugPrintf("<index> * will remove all breakpoints\n"); + return true; + } + + if (strcmp(argv[1], "*") == 0) { + _debugState._breakpoints.clear(); + _debugState._activeBreakpointTypes = 0; return true; } const int idx = atoi(argv[1]); // Find the breakpoint at index idx. - Common::List<Breakpoint>::iterator bp = g_debugState._breakpoints.begin(); - const Common::List<Breakpoint>::iterator end = g_debugState._breakpoints.end(); + Common::List<Breakpoint>::iterator bp = _debugState._breakpoints.begin(); + const Common::List<Breakpoint>::iterator end = _debugState._breakpoints.end(); for (int i = 0; bp != end && i < idx; ++bp, ++i) { // do nothing } @@ -2479,15 +2623,15 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) { } // Delete it - g_debugState._breakpoints.erase(bp); + _debugState._breakpoints.erase(bp); // Update EngineState::_activeBreakpointTypes. int type = 0; - for (bp = g_debugState._breakpoints.begin(); bp != end; ++bp) { + for (bp = _debugState._breakpoints.begin(); bp != end; ++bp) { type |= bp->type; } - g_debugState._activeBreakpointTypes = type; + _debugState._activeBreakpointTypes = type; return true; } @@ -2509,8 +2653,8 @@ bool Console::cmdBreakpointExecMethod(int argc, const char **argv) { bp.type = BREAK_SELECTOR; bp.name = argv[1]; - g_debugState._breakpoints.push_back(bp); - g_debugState._activeBreakpointTypes |= BREAK_SELECTOR; + _debugState._breakpoints.push_back(bp); + _debugState._activeBreakpointTypes |= BREAK_SELECTOR; return true; } @@ -2530,8 +2674,8 @@ bool Console::cmdBreakpointExecFunction(int argc, const char **argv) { bp.type = BREAK_EXPORT; bp.address = (atoi(argv[1]) << 16 | atoi(argv[2])); - g_debugState._breakpoints.push_back(bp); - g_debugState._activeBreakpointTypes |= BREAK_EXPORT; + _debugState._breakpoints.push_back(bp); + _debugState._activeBreakpointTypes |= BREAK_EXPORT; return true; } @@ -2731,9 +2875,9 @@ bool Console::cmdQuit(int argc, const char **argv) { if (!scumm_stricmp(argv[1], "game")) { // Quit gracefully - _engine->_gamestate->script_abort_flag = 1; // Terminate VM - g_debugState.seeking = kDebugSeekNothing; - g_debugState.runningStep = 0; + _engine->_gamestate->abortScriptProcessing = kAbortQuitGame; // Terminate VM + _debugState.seeking = kDebugSeekNothing; + _debugState.runningStep = 0; } else if (!scumm_stricmp(argv[1], "now")) { // Quit ungracefully @@ -2980,8 +3124,71 @@ static int parse_reg_t(EngineState *s, const char *str, reg_t *dest, bool mayBeV return 0; } -void Console::printList(List *l) { - reg_t pos = l->first; +bool Console::parseInteger(const char *argument, int &result) { + char *endPtr = 0; + int idxLen = strlen(argument); + const char *lastChar = argument + idxLen - (idxLen == 0 ? 0 : 1); + + if ((strncmp(argument, "0x", 2) == 0) || (*lastChar == 'h')) { + // hexadecimal number + result = strtol(argument, &endPtr, 16); + if ((*endPtr != 0) && (*endPtr != 'h')) { + DebugPrintf("Invalid hexadecimal number '%s'\n", argument); + return false; + } + } else { + // decimal number + result = strtol(argument, &endPtr, 10); + if (*endPtr != 0) { + DebugPrintf("Invalid decimal number '%s'\n", argument); + return false; + } + } + return true; +} + +void Console::printBasicVarInfo(reg_t variable) { + int regType = g_sci->getKernel()->findRegType(variable); + int segType = regType; + SegManager *segMan = g_sci->getEngineState()->_segMan; + + segType &= SIG_TYPE_INTEGER | SIG_TYPE_OBJECT | SIG_TYPE_REFERENCE | SIG_TYPE_NODE | SIG_TYPE_LIST | SIG_TYPE_UNINITIALIZED | SIG_TYPE_ERROR; + + switch (segType) { + case SIG_TYPE_INTEGER: { + uint16 content = variable.toUint16(); + if (content >= 10) + DebugPrintf(" (%dd)", content); + break; + } + case SIG_TYPE_OBJECT: + DebugPrintf(" (object '%s')", segMan->getObjectName(variable)); + break; + case SIG_TYPE_REFERENCE: + DebugPrintf(" (reference)"); + break; + case SIG_TYPE_NODE: + DebugPrintf(" (node)"); + break; + case SIG_TYPE_LIST: + DebugPrintf(" (list)"); + break; + case SIG_TYPE_UNINITIALIZED: + DebugPrintf(" (uninitialized)"); + break; + case SIG_TYPE_ERROR: + DebugPrintf(" (error)"); + break; + default: + DebugPrintf(" (??\?)"); + } + + if (regType & SIG_IS_INVALID) + DebugPrintf(" IS INVALID!"); +} + +void Console::printList(List *list) { + reg_t pos = list->first; reg_t my_prev = NULL_REG; DebugPrintf("\t<\n"); @@ -3008,9 +3215,9 @@ void Console::printList(List *l) { pos = node->succ; } - if (my_prev != l->last) + if (my_prev != list->last) DebugPrintf(" WARNING: Last node was expected to be %04x:%04x, was %04x:%04x!\n", - PRINT_REG(l->last), PRINT_REG(my_prev)); + PRINT_REG(list->last), PRINT_REG(my_prev)); DebugPrintf("\t>\n"); } @@ -3076,7 +3283,7 @@ int Console::printObject(reg_t pos) { DebugPrintf(" "); if (i < var_container->getVarCount()) { uint16 varSelector = var_container->getVarSelector(i); - DebugPrintf("[%03x] %s = ", varSelector, selector_name(s, varSelector)); + DebugPrintf("[%03x] %s = ", varSelector, _engine->getKernel()->getSelectorName(varSelector).c_str()); } else DebugPrintf("p#%x = ", i); @@ -3095,12 +3302,66 @@ int Console::printObject(reg_t pos) { DebugPrintf(" -- methods:\n"); for (i = 0; i < obj->getMethodCount(); i++) { reg_t fptr = obj->getFunction(i); - DebugPrintf(" [%03x] %s = %04x:%04x\n", obj->getFuncSelector(i), selector_name(s, obj->getFuncSelector(i)), PRINT_REG(fptr)); + DebugPrintf(" [%03x] %s = %04x:%04x\n", obj->getFuncSelector(i), _engine->getKernel()->getSelectorName(obj->getFuncSelector(i)).c_str(), PRINT_REG(fptr)); } if (s->_segMan->_heap[pos.segment]->getType() == SEG_TYPE_SCRIPT) - DebugPrintf("\nOwner script: %d\n", s->_segMan->getScript(pos.segment)->_nr); + DebugPrintf("\nOwner script: %d\n", s->_segMan->getScript(pos.segment)->getScriptNumber()); return 0; } +void Console::hexDumpReg(const reg_t *data, int len, int regsPerLine, int startOffset, bool isArray) { + // reg_t version of Common::hexdump + assert(1 <= regsPerLine && regsPerLine <= 8); + int i; + byte c; + int offset = startOffset; + while (len >= regsPerLine) { + printf("%06x: ", offset); + for (i = 0; i < regsPerLine; i++) { + printf("%04x:%04x ", PRINT_REG(data[i])); + } + printf(" |"); + for (i = 0; i < regsPerLine; i++) { + c = data[i].toUint16() >> 8; + if (c < 32 || c >= 127) + c = '.'; + printf("%c", c); + c = data[i].toUint16() & 0xff; + if (c < 32 || c >= 127) + c = '.'; + printf("%c", c); + } + printf("|\n"); + data += regsPerLine; + len -= regsPerLine; + offset += regsPerLine * (isArray ? 1 : 2); + } + + if (len <= 0) + return; + + printf("%06x: ", offset); + for (i = 0; i < regsPerLine; i++) { + if (i < len) + printf("%04x:%04x ", PRINT_REG(data[i])); + else + printf(" "); + } + printf(" |"); + for (i = 0; i < len; i++) { + c = data[i].toUint16() >> 8; + if (c < 32 || c >= 127) + c = '.'; + printf("%c", c); + c = data[i].toUint16() & 0xff; + if (c < 32 || c >= 127) + c = '.'; + printf("%c", c); + } + for (; i < regsPerLine; i++) + printf(" "); + printf("|\n"); +} + } // End of namespace Sci diff --git a/engines/sci/console.h b/engines/sci/console.h index 2b13e03ef6..51f02d7168 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -74,6 +74,7 @@ private: bool cmdList(int argc, const char **argv); bool cmdHexgrep(int argc, const char **argv); bool cmdVerifyScripts(int argc, const char **argv); + bool cmdShowInstruments(int argc, const char **argv); // Game bool cmdSaveGame(int argc, const char **argv); bool cmdRestoreGame(int argc, const char **argv); @@ -117,9 +118,9 @@ private: bool cmdAddresses(int argc, const char **argv); bool cmdRegisters(int argc, const char **argv); bool cmdDissectScript(int argc, const char **argv); - bool cmdSetAccumulator(int argc, const char **argv); bool cmdBacktrace(int argc, const char **argv); - bool cmdStep(int argc, const char **argv); + bool cmdTrace(int argc, const char **argv); + bool cmdStepOver(int argc, const char **argv); bool cmdStepEvent(int argc, const char **argv); bool cmdStepRet(int argc, const char **argv); bool cmdStepGlobal(int argc, const char **argv); @@ -145,12 +146,18 @@ private: bool cmdViewActiveObject(int argc, const char **argv); bool cmdViewAccumulatorObject(int argc, const char **argv); + bool parseInteger(const char *argument, int &result); + + void printBasicVarInfo(reg_t variable); + bool segmentInfo(int nr); - void printList(List *l); + void printList(List *list); int printNode(reg_t addr); + void hexDumpReg(const reg_t *data, int len, int regsPerLine = 4, int startOffset = 0, bool isArray = false); private: SciEngine *_engine; + DebugState &_debugState; bool _mouseVisible; Common::String _videoFile; int _videoFrameDelay; diff --git a/engines/sci/debug.h b/engines/sci/debug.h index 8383722956..5cf0e38fbc 100644 --- a/engines/sci/debug.h +++ b/engines/sci/debug.h @@ -26,8 +26,8 @@ #ifndef SCI_DEBUG_H #define SCI_DEBUG_H +#include "common/list.h" #include "sci/engine/vm_types.h" // for StackPtr -#include "sci/engine/vm.h" // for ExecStack namespace Sci { @@ -57,8 +57,8 @@ enum DebugSeeking { kDebugSeekCallk = 1, // Step forward until callk is found kDebugSeekLevelRet = 2, // Step forward until returned from this level kDebugSeekSpecialCallk = 3, // Step forward until a /special/ callk is found - kDebugSeekSO = 4, // Step forward until specified PC (after the send command) and stack depth - kDebugSeekGlobal = 5 // Step forward until one specified global variable is modified + kDebugSeekGlobal = 4, // Step forward until one specified global variable is modified + kDebugSeekStepOver = 5 // Step forward until we reach same stack-level again }; struct DebugState { @@ -79,7 +79,6 @@ struct DebugState { extern int g_debug_sleeptime_factor; extern int g_debug_simulated_key; extern bool g_debug_track_mouse_clicks; -extern DebugState g_debugState; } // End of namespace Sci diff --git a/engines/sci/decompressor.cpp b/engines/sci/decompressor.cpp index 84af50b596..96c7f24ef6 100644 --- a/engines/sci/decompressor.cpp +++ b/engines/sci/decompressor.cpp @@ -574,15 +574,17 @@ void DecompressorLZW::reorderView(byte *src, byte *dest) { for (c = 0; c < cel_total; c++) decodeRLE(&rle_ptr, &pix_ptr, cc_pos[c] + 8, cc_lengths[c]); - *writer++ = 'P'; - *writer++ = 'A'; - *writer++ = 'L'; + if (pal_offset) { + *writer++ = 'P'; + *writer++ = 'A'; + *writer++ = 'L'; - for (c = 0; c < 256; c++) - *writer++ = c; + for (c = 0; c < 256; c++) + *writer++ = c; - seeker -= 4; /* The missing four. Don't ask why. */ - memcpy(writer, seeker, 4*256 + 4); + seeker -= 4; /* The missing four. Don't ask why. */ + memcpy(writer, seeker, 4*256 + 4); + } free(cc_pos); free(cc_lengths); diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 1ccfc6bf02..eb2c989e0d 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -36,12 +36,11 @@ #include "sci/engine/script.h" #include "sci/engine/seg_manager.h" #include "sci/engine/state.h" -#include "sci/engine/vm.h" // for convertSierraGameId namespace Sci { // Titles of the games -static const PlainGameDescriptor SciGameTitles[] = { +static const PlainGameDescriptor s_sciGameTitles[] = { {"sci", "Sierra SCI Game"}, {"sci-fanmade", "Fanmade SCI Game"}, // === SCI0 games ========================================================= @@ -106,6 +105,7 @@ static const PlainGameDescriptor SciGameTitles[] = { // TODO: Inside The Chest/Behind the Developer's Shield {"kq7", "King's Quest VII: The Princeless Bride"}, // TODO: King's Questions + {"lsl6hires", "Leisure Suit Larry 6: Shape Up or Slip Out!"}, {"phantasmagoria", "Phantasmagoria"}, {"pqswat", "Police Quest: SWAT"}, {"shivers", "Shivers"}, @@ -120,6 +120,81 @@ static const PlainGameDescriptor SciGameTitles[] = { {0, 0} }; +struct GameIdStrToEnum { + const char *gameidStr; + SciGameId gameidEnum; +}; + +static const GameIdStrToEnum s_gameIdStrToEnum[] = { + { "astrochicken", GID_ASTROCHICKEN }, + { "camelot", GID_CAMELOT }, + { "castlebrain", GID_CASTLEBRAIN }, + { "christmas1988", GID_CHRISTMAS1988 }, + { "christmas1990", GID_CHRISTMAS1990 }, + { "christmas1992", GID_CHRISTMAS1992 }, + { "cnick-kq", GID_CNICK_KQ }, + { "cnick-laurabow", GID_CNICK_LAURABOW }, + { "cnick-longbow", GID_CNICK_LONGBOW }, + { "cnick-lsl", GID_CNICK_LSL }, + { "cnick-sq", GID_CNICK_SQ }, + { "ecoquest", GID_ECOQUEST }, + { "ecoquest2", GID_ECOQUEST2 }, + { "fairytales", GID_FAIRYTALES }, + { "freddypharkas", GID_FREDDYPHARKAS }, + { "funseeker", GID_FUNSEEKER }, + { "gk1", GID_GK1 }, + { "gk2", GID_GK2 }, + { "hoyle1", GID_HOYLE1 }, + { "hoyle2", GID_HOYLE2 }, + { "hoyle3", GID_HOYLE3 }, + { "hoyle4", GID_HOYLE4 }, + { "iceman", GID_ICEMAN }, + { "islandbrain", GID_ISLANDBRAIN }, + { "jones", GID_JONES }, + { "kq1sci", GID_KQ1 }, + { "kq4sci", GID_KQ4 }, + { "kq5", GID_KQ5 }, + { "kq6", GID_KQ6 }, + { "kq7", GID_KQ7 }, + { "laurabow", GID_LAURABOW }, + { "laurabow2", GID_LAURABOW2 }, + { "lighthouse", GID_LIGHTHOUSE }, + { "longbow", GID_LONGBOW }, + { "lsl1sci", GID_LSL1 }, + { "lsl2", GID_LSL2 }, + { "lsl3", GID_LSL3 }, + { "lsl5", GID_LSL5 }, + { "lsl6", GID_LSL6 }, + { "lsl6hires", GID_LSL6HIRES }, + { "lsl7", GID_LSL7 }, + { "mothergoose", GID_MOTHERGOOSE }, + { "msastrochicken", GID_MSASTROCHICKEN }, + { "pepper", GID_PEPPER }, + { "phantasmagoria", GID_PHANTASMAGORIA }, + { "phantasmagoria2", GID_PHANTASMAGORIA2 }, + { "pq1sci", GID_PQ1 }, + { "pq2", GID_PQ2 }, + { "pq3", GID_PQ3 }, + { "pq4", GID_PQ4 }, + { "pqswat", GID_PQSWAT }, + { "qfg1", GID_QFG1 }, + { "qfg2", GID_QFG2 }, + { "qfg3", GID_QFG3 }, + { "qfg4", GID_QFG4 }, + { "rama", GID_RAMA }, + { "sci-fanmade", GID_FANMADE }, // FIXME: Do we really need/want this? + { "shivers", GID_SHIVERS }, + { "shivers2", GID_SHIVERS2 }, + { "slater", GID_SLATER }, + { "sq1sci", GID_SQ1 }, + { "sq3", GID_SQ3 }, + { "sq4", GID_SQ4 }, + { "sq5", GID_SQ5 }, + { "sq6", GID_SQ6 }, + { "torin", GID_TORIN }, + { NULL, (SciGameId)-1 } +}; + struct OldNewIdTableEntry { const char *oldId; const char *newId; @@ -198,6 +273,12 @@ static const OldNewIdTableEntry s_oldNewTable[] = { { "", "", SCI_VERSION_NONE } }; +/** + * Converts the builtin Sierra game IDs to the ones we use in ScummVM + * @param[in] gameId The internal game ID + * @param[in] gameFlags The game's flags, which are adjusted accordingly for demos + * @return The equivalent ScummVM game id + */ Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, ResourceManager *resMan) { // Convert the id to lower case, so that we match all upper/lower case variants. sierraId.toLowercase(); @@ -295,7 +376,7 @@ static const ADParams detectionParams = { // Number of bytes to compute MD5 sum for 5000, // List of all engine targets - SciGameTitles, + s_sciGameTitles, // Structure for autoupgrading obsolete targets 0, // Name of single gameid (optional) @@ -305,7 +386,11 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NONE + Common::GUIO_NONE, + // Maximum directory depth + 1, + // List of directory globs + 0 }; class SciMetaEngine : public AdvancedMetaEngine { @@ -419,7 +504,12 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl return 0; } - ResourceManager *resMan = new ResourceManager(fslist); + ResourceManager *resMan = new ResourceManager(); + assert(resMan); + resMan->addAppropriateSources(fslist); + resMan->init(); + // TODO: Add error handling. + ViewType gameViews = resMan->getViewType(); // Have we identified the game views? If not, stop here @@ -509,12 +599,16 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl return (const ADGameDescription *)&s_fallbackDesc; } -bool SciMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const { - const ADGameDescription *desc = (const ADGameDescription *)gd; - - *engine = new SciEngine(syst, desc); +bool SciMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { + const GameIdStrToEnum *g = s_gameIdStrToEnum; + for (; g->gameidStr; ++g) { + if (0 == strcmp(desc->gameid, g->gameidStr)) { + *engine = new SciEngine(syst, desc, g->gameidEnum); + return true; + } + } - return true; + return false; } bool SciMetaEngine::hasFeature(MetaEngineFeature f) const { @@ -652,7 +746,7 @@ Common::Error SciEngine::saveGameState(int slot, const char *desc) { return Common::kWritingFailed; } - if (gamestate_save(_gamestate, out, desc, version)) { + if (!gamestate_save(_gamestate, out, desc, version)) { warning("Saving the game state to '%s' failed", fileName.c_str()); return Common::kWritingFailed; } else { @@ -668,11 +762,11 @@ Common::Error SciEngine::saveGameState(int slot, const char *desc) { } bool SciEngine::canLoadGameStateCurrently() { - return !_gamestate->execution_stack_base; + return !_gamestate->executionStackBase; } bool SciEngine::canSaveGameStateCurrently() { - return !_gamestate->execution_stack_base; + return !_gamestate->executionStackBase; } } // End of namespace Sci diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index dba4d879aa..aa1e26e0f4 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -753,14 +753,31 @@ static const struct ADGameDescription SciGameDescriptions[] = { Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH }, // Hoyle 4 - English DOS Demo + {"hoyle4", "Demo", { + {"resource.map", 0, "60f764020a6b788bbbe415dbc2ccb9f3", 931}, + {"resource.000", 0, "5fe3670e3ddcd4f85c10013b5453141a", 615522}, + {NULL, 0, NULL, 0}}, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH }, + + // Hoyle 4 - English DOS Demo // SCI interpreter version 1.001.200 (just a guess) + // Does anyone have this version? -clone2727 {"hoyle4", "Demo", { {"resource.map", 0, "662087cb383e52e3cc4ae7ecb10e20aa", 938}, {"resource.000", 0, "24c10844792c54d476d272213cbac300", 675252}, {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH }, - // Jones in the Fast Lane - English DOS + // Jones in the Fast Lane EGA - English DOS + // SCI interpreter version 1.000.172 (not 100% sure FIXME) + {"jones", "", { + {"resource.map", 0, "be4cf9e8c1e253623ef35ae3b8a1d998", 1800}, + {"resource.001", 0, "bac3ec6cb3e3920984ab0f32becf5163", 202105}, + {"resource.002", 0, "b86daa3ba2784d1502da881eedb80d9b", 341771}, + {NULL, 0, NULL, 0}}, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH }, + + // Jones in the Fast Lane VGA - English DOS // SCI interpreter version 1.000.172 {"jones", "", { {"resource.map", 0, "65cbe19b36fffc71c8e7b2686bd49ad7", 1800}, @@ -1667,7 +1684,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { #ifdef ENABLE_SCI32 // Larry 6 - English/German DOS CD - HIRES // SCI interpreter version 2.100.002 - {"lsl6", "", { + {"lsl6hires", "", { {"resource.map", 0, "0c0804434ea62278dd15032b1947426c", 8872}, {"resource.000", 0, "9a9f4870504444cda863dd14d077a680", 18520872}, {NULL, 0, NULL, 0}}, @@ -1675,7 +1692,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { // Larry 6 - German DOS CD - HIRES (provided by richiefs in bug report #2670691) // SCI interpreter version 2.100.002 - {"lsl6", "", { + {"lsl6hires", "", { {"resource.map", 0, "badfdf446ffed569a310d2c63a249421", 8896}, {"resource.000", 0, "bd944d2b06614a5b39f1586906f0ee88", 18534274}, {NULL, 0, NULL, 0}}, @@ -1683,7 +1700,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { // Larry 6 - French DOS CD - HIRES (provided by richiefs in bug report #2670691) // SCI interpreter version 2.100.002 - {"lsl6", "", { + {"lsl6hires", "", { {"resource.map", 0, "d184e9aa4f2d4b5670ddb3669db82cda", 8896}, {"resource.000", 0, "bd944d2b06614a5b39f1586906f0ee88", 18538987}, {NULL, 0, NULL, 0}}, @@ -2390,7 +2407,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { }, // Quest for Glory 4 1.1 Floppy - German DOS (supplied by markcool in bug report #2723850) - // SCI interpreter version 2.000.000 (a guess?) + // Executable scanning reports "2.000.000", VERSION file reports "1.1" {"qfg4", "", { {"resource.map", 0, "9e0abba8746f40565bc7eb5720522ecd", 9301}, {"resource.000", 0, "57f22cdc54eeb35fce1f26b31b5c3ee1", 11076197}, @@ -2407,27 +2424,6 @@ static const struct ADGameDescription SciGameDescriptions[] = { Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH }, -#if 0 - // NOTE: This version looks to be exactly the same as the English one - // Perhaps it's the English one? - - // Quest for Glory 4 - German DOS/Windows (from PCJoker 2/98) - {"qfg4", "", { - {"resource.map", 0, "aba367f2102e81782d961b14fbe3d630", 10246}, - {"resource.000", 0, "263dce4aa34c49d3ad29bec889007b1c", 11571394}, - {NULL, 0, NULL, 0}}, - Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH - }, -#endif - - // Quest for Glory 4 - German DOS/Windows Disk V1.1 (from PCJoker 2/89) - // SCI interpreter version 2.000.000 (a guess?) - {"qfg4", "", { - {"resource.map", 0, "9e0abba8746f40565bc7eb5720522ecd", 9301}, - {"resource.000", 0, "57f22cdc54eeb35fce1f26b31b5c3ee1", 11076197}, - {NULL, 0, NULL, 0}}, - Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH - }, #endif // Slater & Charlie go camping @@ -2572,6 +2568,18 @@ static const struct ADGameDescription SciGameDescriptions[] = { Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH }, + // Space Quest 1 VGA Remake - English Mac (from Fingolfin) + {"sq1sci", "VGA Remake", { + {"resource.map", 0, "5c6ad20407261b544238e8dce87afead", 5895}, + {"resource.000", 0, "2c414644b23839069c8d1a93b721df16", 1017033}, + {"resource.001", 0, "8744ae2ea6b316e91e2a35ab1aa301d2", 1024622}, + {"resource.002", 0, "96860704f7a07ecc10bef223b4b2f153", 1273992}, + {"resource.003", 0, "ae46e195e66df5a131917f0aa80b5669", 1242794}, + {"resource.004", 0, "91d58a9eb2187c38424990afe4c12bc6", 1250949}, + {NULL, 0, NULL, 0}}, + Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_NOSPEECH + }, + // Space Quest 1 VGA Remake - English Non-Interactive Demo (from FRG) // SCI interpreter version 1.000.181 {"sq1sci", "VGA Remake, Demo", { @@ -2660,6 +2668,15 @@ static const struct ADGameDescription SciGameDescriptions[] = { {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH }, + // Space Quest 3 - English Mac (from Fingolfin) + {"sq3", "", { + {"resource.map", 0, "5c931675c6e01c4b418faca85d76c92c", 5844}, + {"resource.001", 0, "0d8dfe42683b46f3131823233a91ce6a", 771917}, + {"resource.002", 0, "0d8dfe42683b46f3131823233a91ce6a", 794072}, + {"resource.003", 0, "0d8dfe42683b46f3131823233a91ce6a", 776536}, + {NULL, 0, NULL, 0}}, + Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_NOSPEECH }, + // Space Quest 3 - German DOS (from Tobis87) // SCI interpreter version 0.000.453 (?) {"sq3", "", { diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp index 48f7c2d64f..fee6e69da7 100644 --- a/engines/sci/engine/features.cpp +++ b/engines/sci/engine/features.cpp @@ -24,6 +24,7 @@ */ #include "sci/engine/features.h" +#include "sci/engine/kernel.h" #include "sci/engine/script.h" #include "sci/engine/selector.h" #include "sci/engine/vm.h" @@ -51,13 +52,13 @@ reg_t GameFeatures::getDetectionAddr(const Common::String &objName, Selector slc reg_t addr; if (objAddr.isNull()) { - warning("getDetectionAddr: %s object couldn't be found", objName.c_str()); + error("getDetectionAddr: %s object couldn't be found", objName.c_str()); return NULL_REG; } if (methodNum == -1) { if (lookupSelector(_segMan, objAddr, slc, NULL, &addr) != kSelectorMethod) { - warning("getDetectionAddr: target selector is not a method of object %s", objName.c_str()); + error("getDetectionAddr: target selector is not a method of object %s", objName.c_str()); return NULL_REG; } } else { @@ -69,7 +70,7 @@ reg_t GameFeatures::getDetectionAddr(const Common::String &objName, Selector slc bool GameFeatures::autoDetectSoundType() { // Look up the script address - reg_t addr = getDetectionAddr("Sound", _kernel->_selectorCache.play); + reg_t addr = getDetectionAddr("Sound", SELECTOR(play)); if (!addr.segment) return false; @@ -83,17 +84,17 @@ bool GameFeatures::autoDetectSoundType() { int16 opparams[4]; byte extOpcode; byte opcode; - offset += readPMachineInstruction(script->_buf + offset, extOpcode, opparams); + offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams); opcode = extOpcode >> 1; // Check for end of script if (opcode == op_ret || offset >= script->getBufSize()) break; - // The play method of the Sound object pushes the DoSound command - // that it'll use just before it calls DoSound. We intercept that here - // in order to check what sound semantics are used, cause the position - // of the sound commands has changed at some point during SCI1 middle + // The play method of the Sound object pushes the DoSound command that + // it will use just before it calls DoSound. We intercept that here in + // order to check what sound semantics are used, cause the position of + // the sound commands has changed at some point during SCI1 middle. if (opcode == op_pushi) { // Load the pushi parameter intParam = opparams[0]; @@ -104,8 +105,8 @@ bool GameFeatures::autoDetectSoundType() { if (kFuncNum == 6) { // kIsObject (SCI0-SCI11) foundTarget = true; } else if (kFuncNum == 45) { // kDoSound (SCI1) - // First, check which DoSound function is called by the play method of - // the Sound object + // First, check which DoSound function is called by the play + // method of the Sound object switch (intParam) { case 1: _doSoundType = SCI_VERSION_0_EARLY; @@ -118,8 +119,8 @@ bool GameFeatures::autoDetectSoundType() { break; default: // Unknown case... should never happen. We fall back to - // alternative detection here, which works in general, apart from - // some transitive games like Jones CD + // alternative detection here, which works in general, apart + // from some transitive games like Jones CD _doSoundType = foundTarget ? SCI_VERSION_1_LATE : SCI_VERSION_1_EARLY; break; } @@ -136,9 +137,10 @@ bool GameFeatures::autoDetectSoundType() { SciVersion GameFeatures::detectDoSoundType() { if (_doSoundType == SCI_VERSION_NONE) { if (getSciVersion() == SCI_VERSION_0_EARLY) { - // This game is using early SCI0 sound code (different headers than SCI0 late) + // This game is using early SCI0 sound code (different headers than + // SCI0 late) _doSoundType = SCI_VERSION_0_EARLY; - } else if (_kernel->_selectorCache.nodePtr == -1) { + } else if (SELECTOR(nodePtr) == -1) { // No nodePtr selector, so this game is definitely using newer // SCI0 sound code (i.e. SCI_VERSION_0_LATE) _doSoundType = SCI_VERSION_0_LATE; @@ -171,14 +173,16 @@ SciVersion GameFeatures::detectSetCursorType() { // SCI1.1 games always use cursor views _setCursorType = SCI_VERSION_1_1; } else { // SCI1 late game, detect cursor semantics - // If the Cursor object doesn't exist, we're using the SCI0 early kSetCursor semantics. + // If the Cursor object doesn't exist, we're using the SCI0 early + // kSetCursor semantics. if (_segMan->findObjectByName("Cursor") == NULL_REG) { _setCursorType = SCI_VERSION_0_EARLY; debugC(1, kDebugLevelGraphics, "Detected SetCursor type: %s", getSciVersionDesc(_setCursorType)); return _setCursorType; } - // Check for the existence of the handCursor object (first found). This is based on KQ5. + // Check for the existence of the handCursor object (first found). + // This is based on KQ5. reg_t objAddr = _segMan->findObjectByName("handCursor", 0); // If that doesn't exist, we assume it uses SCI1.1 kSetCursor semantics @@ -188,11 +192,13 @@ SciVersion GameFeatures::detectSetCursorType() { return _setCursorType; } - // Now we check what the number variable holds in the handCursor object. + // Now we check what the number variable holds in the handCursor + // object. uint16 number = readSelectorValue(_segMan, objAddr, SELECTOR(number)); - // If the number is 0, it uses views and therefore the SCI1.1 kSetCursor semantics, - // otherwise it uses the SCI0 early kSetCursor semantics. + // If the number is 0, it uses views and therefore the SCI1.1 + // kSetCursor semantics, otherwise it uses the SCI0 early kSetCursor + // semantics. if (number == 0) _setCursorType = SCI_VERSION_1_1; else @@ -219,7 +225,7 @@ bool GameFeatures::autoDetectLofsType(int methodNum) { int16 opparams[4]; byte extOpcode; byte opcode; - offset += readPMachineInstruction(script->_buf + offset, extOpcode, opparams); + offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams); opcode = extOpcode >> 1; // Check for end of script @@ -293,7 +299,7 @@ SciVersion GameFeatures::detectLofsType() { bool GameFeatures::autoDetectGfxFunctionsType(int methodNum) { // Look up the script address - reg_t addr = getDetectionAddr("Rm", _kernel->_selectorCache.overlay, methodNum); + reg_t addr = getDetectionAddr("Rm", SELECTOR(overlay), methodNum); if (!addr.segment) return false; @@ -305,7 +311,7 @@ bool GameFeatures::autoDetectGfxFunctionsType(int methodNum) { int16 opparams[4]; byte extOpcode; byte opcode; - offset += readPMachineInstruction(script->_buf + offset, extOpcode, opparams); + offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams); opcode = extOpcode >> 1; // Check for end of script @@ -317,10 +323,10 @@ bool GameFeatures::autoDetectGfxFunctionsType(int methodNum) { uint16 argc = opparams[1]; if (kFuncNum == 8) { // kDrawPic (SCI0 - SCI11) - // If kDrawPic is called with 6 parameters from the - // overlay selector, the game is using old graphics functions. + // If kDrawPic is called with 6 parameters from the overlay + // selector, the game is using old graphics functions. // Otherwise, if it's called with 8 parameters, it's using new - // graphics functions + // graphics functions. _gfxFunctionsType = (argc == 8) ? SCI_VERSION_0_LATE : SCI_VERSION_0_EARLY; return true; } @@ -343,33 +349,36 @@ SciVersion GameFeatures::detectGfxFunctionsType() { bool searchRoomObj = false; reg_t rmObjAddr = _segMan->findObjectByName("Rm"); - if (_kernel->_selectorCache.overlay != -1) { - // The game has an overlay selector, check how it calls kDrawPicto determine - // the graphics functions type used - if (lookupSelector(_segMan, rmObjAddr, _kernel->_selectorCache.overlay, NULL, NULL) == kSelectorMethod) { + if (SELECTOR(overlay) != -1) { + // The game has an overlay selector, check how it calls kDrawPic + // to determine the graphics functions type used + if (lookupSelector(_segMan, rmObjAddr, SELECTOR(overlay), NULL, NULL) == kSelectorMethod) { if (!autoDetectGfxFunctionsType()) { warning("Graphics functions detection failed, taking an educated guess"); - // Try detecting the graphics function types from the existence of the motionCue - // selector (which is a bit of a hack) + // Try detecting the graphics function types from the + // existence of the motionCue selector (which is a bit + // of a hack) if (_kernel->findSelector("motionCue") != -1) _gfxFunctionsType = SCI_VERSION_0_LATE; else _gfxFunctionsType = SCI_VERSION_0_EARLY; } } else { - // The game has an overlay selector, but it's not a method of the Rm object - // (like in Hoyle 1 and 2), so search for other methods + // The game has an overlay selector, but it's not a method + // of the Rm object (like in Hoyle 1 and 2), so search for + // other methods searchRoomObj = true; } } else { - // The game doesn't have an overlay selector, so search for it manually + // The game doesn't have an overlay selector, so search for it + // manually searchRoomObj = true; } if (searchRoomObj) { - // If requested, check if any method of the Rm object is calling kDrawPic, - // as the overlay selector might be missing in demos + // If requested, check if any method of the Rm object is calling + // kDrawPic, as the overlay selector might be missing in demos bool found = false; const Object *obj = _segMan->getObject(rmObjAddr); @@ -380,8 +389,9 @@ SciVersion GameFeatures::detectGfxFunctionsType() { } if (!found) { - // No method of the Rm object is calling kDrawPic, thus the game - // doesn't have overlays and is using older graphics functions + // No method of the Rm object is calling kDrawPic, thus the + // game doesn't have overlays and is using older graphics + // functions _gfxFunctionsType = SCI_VERSION_0_EARLY; } } @@ -395,8 +405,20 @@ SciVersion GameFeatures::detectGfxFunctionsType() { #ifdef ENABLE_SCI32 bool GameFeatures::autoDetectSci21KernelType() { + // First, check if the Sound object is loaded + reg_t soundObjAddr = _segMan->findObjectByName("Sound"); + if (soundObjAddr.isNull()) { + // Usually, this means that the Sound object isn't loaded yet. + // This case doesn't occur in early SCI2.1 games, and we've only + // seen it happen in the RAMA demo, thus we can assume that the + // game is using a SCI2.1 table + warning("autoDetectSci21KernelType(): Sound object not loaded, assuming a SCI2.1 table"); + _sci21KernelType = SCI_VERSION_2_1; + return true; + } + // Look up the script address - reg_t addr = getDetectionAddr("Sound", _kernel->_selectorCache.play); + reg_t addr = getDetectionAddr("Sound", SELECTOR(play)); if (!addr.segment) return false; @@ -408,7 +430,7 @@ bool GameFeatures::autoDetectSci21KernelType() { int16 opparams[4]; byte extOpcode; byte opcode; - offset += readPMachineInstruction(script->_buf + offset, extOpcode, opparams); + offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams); opcode = extOpcode >> 1; // Check for end of script @@ -419,9 +441,11 @@ bool GameFeatures::autoDetectSci21KernelType() { uint16 kFuncNum = opparams[0]; // Here we check for the kDoSound opcode that's used in SCI2.1. - // Finding 0x40 as kDoSound in the Sound::play() function means the game is using - // the modified SCI2 kernel table found in some older SCI2.1 games (GK2 demo, KQ7 v1.4). - // Finding 0x75 as kDoSound means the game is using the regular SCI2.1 kernel table. + // Finding 0x40 as kDoSound in the Sound::play() function means the + // game is using the modified SCI2 kernel table found in some older + // SCI2.1 games (GK2 demo, KQ7 v1.4). + // Finding 0x75 as kDoSound means the game is using the regular + // SCI2.1 kernel table. if (kFuncNum == 0x40) { _sci21KernelType = SCI_VERSION_2; return true; @@ -448,7 +472,7 @@ SciVersion GameFeatures::detectSci21KernelType() { bool GameFeatures::autoDetectMoveCountType() { // Look up the script address - reg_t addr = getDetectionAddr("Motion", _kernel->_selectorCache.doit); + reg_t addr = getDetectionAddr("Motion", SELECTOR(doit)); if (!addr.segment) return false; @@ -461,7 +485,7 @@ bool GameFeatures::autoDetectMoveCountType() { int16 opparams[4]; byte extOpcode; byte opcode; - offset += readPMachineInstruction(script->_buf + offset, extOpcode, opparams); + offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams); opcode = extOpcode >> 1; // Check for end of script @@ -491,7 +515,7 @@ MoveCountType GameFeatures::detectMoveCountType() { _moveCountType = kIncrementMoveCount; } else { if (!autoDetectMoveCountType()) { - warning("Move count autodetection failed"); + error("Move count autodetection failed"); _moveCountType = kIncrementMoveCount; // Most games do this, so best guess } } diff --git a/engines/sci/engine/features.h b/engines/sci/engine/features.h index 77c2f0cff7..5b383746d8 100644 --- a/engines/sci/engine/features.h +++ b/engines/sci/engine/features.h @@ -31,6 +31,12 @@ namespace Sci { +enum MoveCountType { + kMoveCountUninitialized, + kIgnoreMoveCount, + kIncrementMoveCount +}; + class GameFeatures { public: GameFeatures(SegManager *segMan, Kernel *kernel); diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp deleted file mode 100644 index bc10099e52..0000000000 --- a/engines/sci/engine/game.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/system.h" -#include "common/file.h" - -#include "engines/advancedDetector.h" // for ADGF_DEMO - -#include "sci/sci.h" -#include "sci/resource.h" -#include "sci/engine/features.h" -#include "sci/engine/state.h" -#include "sci/engine/kernel.h" -#include "sci/engine/message.h" -#include "sci/graphics/gui.h" -#include "sci/graphics/menu.h" -#include "sci/sound/audio.h" -#include "sci/sound/music.h" - -namespace Sci { - -#ifdef USE_OLD_MUSIC_FUNCTIONS -int game_init_sound(EngineState *s, int sound_flags, SciVersion soundVersion) { - if (getSciVersion() > SCI_VERSION_0_LATE) - sound_flags |= SFX_STATE_FLAG_MULTIPLAY; - - s->sfx_init_flags = sound_flags; - s->_sound.sfx_init(g_sci->getResMan(), sound_flags, soundVersion); - - return 0; -} -#endif - -// Architectural stuff: Init/Unintialize engine -int script_init_engine(EngineState *s) { - s->_msgState = new MessageState(s->_segMan); - s->gc_countdown = GC_INTERVAL - 1; - - SegmentId script_000_segment = s->_segMan->getScriptSegment(0, SCRIPT_GET_LOCK); - - if (script_000_segment <= 0) { - debug(2, "Failed to instantiate script.000"); - return 1; - } - - s->script_000 = s->_segMan->getScript(script_000_segment); - - s->_segMan->initSysStrings(); - - s->r_acc = s->r_prev = NULL_REG; - s->restAdjust = 0; - - s->_executionStack.clear(); // Start without any execution stack - s->execution_stack_base = -1; // No vm is running yet - - s->restarting_flags = SCI_GAME_IS_NOT_RESTARTING; - - debug(2, "Engine initialized"); - - return 0; -} - -/*************************************************************/ -/* Game instance stuff: Init/Unitialize state-dependant data */ -/*************************************************************/ - -int game_init(EngineState *s) { - // FIXME Use new VM instantiation code all over the place - DataStack *stack; - - stack = s->_segMan->allocateStack(VM_STACK_SIZE, NULL); - s->stack_base = stack->_entries; - s->stack_top = stack->_entries + stack->_capacity; - - if (!script_instantiate(g_sci->getResMan(), s->_segMan, 0)) { - warning("game_init(): Could not instantiate script 0"); - return 1; - } - - // Reset parser - Vocabulary *voc = g_sci->getVocabulary(); - if (voc) { - voc->parserIsValid = false; // Invalidate parser - voc->parser_event = NULL_REG; // Invalidate parser event - voc->parser_base = make_reg(s->_segMan->getSysStringsSegment(), SYS_STRING_PARSER_BASE); - } - - // Initialize menu TODO: Actually this should be another init() - if (g_sci->_gfxMenu) - g_sci->_gfxMenu->reset(); - - s->restoring = false; - - s->game_start_time = g_system->getMillis(); - s->last_wait_time = s->game_start_time; - - srand(g_system->getMillis()); // Initialize random number generator - - s->_gameObj = g_sci->getResMan()->findGameObject(); - -#ifdef USE_OLD_MUSIC_FUNCTIONS - if (s->sfx_init_flags & SFX_STATE_FLAG_NOSOUND) - game_init_sound(s, 0, g_sci->_features->detectDoSoundType()); -#endif - - // Load game language into printLang property of game object - // FIXME: It's evil to achieve this as a side effect of a getter. - // Much better to have an explicit init method for this. - g_sci->getSciLanguage(); - - return 0; -} - -int game_exit(EngineState *s) { - if (!s->restoring) { - s->_executionStack.clear(); -#ifdef USE_OLD_MUSIC_FUNCTIONS - s->_sound.sfx_exit(); - // Reinit because some other code depends on having a valid state - game_init_sound(s, SFX_STATE_FLAG_NOSOUND, g_sci->_features->detectDoSoundType()); -#else - g_sci->_audio->stopAllAudio(); - s->_soundCmd->clearPlayList(); -#endif - } - - // Note: It's a bad idea to delete the segment manager here - // when loading a game. - // This function is called right after a game is loaded, and - // the segment manager has already been initialized from the - // save game. Deleting or resetting it here will result in - // invalidating the loaded save state - if (s->restarting_flags & SCI_GAME_IS_RESTARTING_NOW) - s->_segMan->resetSegMan(); - - // TODO Free parser segment here - - // TODO Free scripts here - - // Close all opened file handles - s->_fileHandles.clear(); - s->_fileHandles.resize(5); - - return 0; -} - -} // End of namespace Sci diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp index c2f1c15776..936b83d760 100644 --- a/engines/sci/engine/gc.cpp +++ b/engines/sci/engine/gc.cpp @@ -28,11 +28,9 @@ namespace Sci { -//#define DEBUG_GC - struct WorklistManager { Common::Array<reg_t> _worklist; - reg_t_hash_map _map; + AddrSet _map; void push(reg_t reg) { if (!reg.segment) // No numbers @@ -46,14 +44,19 @@ struct WorklistManager { _map.setVal(reg, true); _worklist.push_back(reg); } + + void pushArray(const Common::Array<reg_t> &tmp) { + for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) + push(*it); + } }; -static reg_t_hash_map *normalise_hashmap_ptrs(SegManager *segMan, reg_t_hash_map &nonnormal_map) { - reg_t_hash_map *normal_map = new reg_t_hash_map(); +static AddrSet *normalizeAddresses(SegManager *segMan, const AddrSet &nonnormal_map) { + AddrSet *normal_map = new AddrSet(); - for (reg_t_hash_map::iterator i = nonnormal_map.begin(); i != nonnormal_map.end(); ++i) { + for (AddrSet::const_iterator i = nonnormal_map.begin(); i != nonnormal_map.end(); ++i) { reg_t reg = i->_key; - SegmentObj *mobj = (reg.segment < segMan->_heap.size()) ? segMan->_heap[reg.segment] : NULL; + SegmentObj *mobj = segMan->getSegmentObj(reg.segment); if (mobj) { reg = mobj->findCanonicAddress(segMan, reg); @@ -65,14 +68,9 @@ static reg_t_hash_map *normalise_hashmap_ptrs(SegManager *segMan, reg_t_hash_map } -void add_outgoing_refs(void *refcon, reg_t addr) { - WorklistManager *wm = (WorklistManager *)refcon; - wm->push(addr); -} - -reg_t_hash_map *find_all_used_references(EngineState *s) { +AddrSet *findAllActiveReferences(EngineState *s) { SegManager *segMan = s->_segMan; - reg_t_hash_map *normal_map = NULL; + AddrSet *normal_map = NULL; WorklistManager wm; uint i; @@ -84,22 +82,19 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { wm.push(s->r_prev); // Init: Value Stack // We do this one by hand since the stack doesn't know the current execution stack - Common::List<ExecStack>::iterator iter; - { - iter = s->_executionStack.reverse_begin(); + Common::List<ExecStack>::iterator iter = s->_executionStack.reverse_begin(); - // Skip fake kernel stack frame if it's on top - if (((*iter).type == EXEC_STACK_TYPE_KERNEL)) - --iter; + // Skip fake kernel stack frame if it's on top + if (((*iter).type == EXEC_STACK_TYPE_KERNEL)) + --iter; - assert((iter != s->_executionStack.end()) && ((*iter).type != EXEC_STACK_TYPE_KERNEL)); + assert((iter != s->_executionStack.end()) && ((*iter).type != EXEC_STACK_TYPE_KERNEL)); - ExecStack &xs = *iter; - reg_t *pos; + ExecStack &xs = *iter; + reg_t *pos; - for (pos = s->stack_base; pos < xs.sp; pos++) - wm.push(*pos); - } + for (pos = s->stack_base; pos < xs.sp; pos++) + wm.push(*pos); debugC(2, kDebugLevelGC, "[GC] -- Finished adding value stack"); @@ -118,24 +113,18 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { debugC(2, kDebugLevelGC, "[GC] -- Finished adding execution stack"); + const Common::Array<SegmentObj *> &heap = segMan->getSegments(); + // Init: Explicitly loaded scripts - for (i = 1; i < segMan->_heap.size(); i++) - if (segMan->_heap[i] - && segMan->_heap[i]->getType() == SEG_TYPE_SCRIPT) { - Script *script = (Script *)segMan->_heap[i]; + for (i = 1; i < heap.size(); i++) { + if (heap[i] && heap[i]->getType() == SEG_TYPE_SCRIPT) { + Script *script = (Script *)heap[i]; if (script->getLockers()) { // Explicitly loaded? - // Locals, if present - wm.push(make_reg(script->_localsSegment, 0)); - - // All objects (may be classes, may be indirectly reachable) - ObjMap::iterator it; - const ObjMap::iterator end = script->_objects.end(); - for (it = script->_objects.begin(); it != end; ++it) { - wm.push(it->_value.getPos()); - } + wm.pushArray(script->listObjectReferences()); } } + } debugC(2, kDebugLevelGC, "[GC] -- Finished explicitly loaded scripts, done with root set"); @@ -146,76 +135,64 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { wm._worklist.pop_back(); if (reg.segment != stack_seg) { // No need to repeat this one debugC(2, kDebugLevelGC, "[GC] Checking %04x:%04x", PRINT_REG(reg)); - if (reg.segment < segMan->_heap.size() && segMan->_heap[reg.segment]) - segMan->_heap[reg.segment]->listAllOutgoingReferences(reg, &wm, add_outgoing_refs); + if (reg.segment < heap.size() && heap[reg.segment]) { + // Valid heap object? Find its outgoing references! + wm.pushArray(heap[reg.segment]->listAllOutgoingReferences(reg)); + } } } // Normalise - normal_map = normalise_hashmap_ptrs(segMan, wm._map); + normal_map = normalizeAddresses(segMan, wm._map); return normal_map; } -struct deallocator_t { - SegManager *segMan; - SegmentObj *mobj; -#ifdef DEBUG_GC - char *segnames[SEG_TYPE_MAX + 1]; - int segcount[SEG_TYPE_MAX + 1]; -#endif - reg_t_hash_map *use_map; -}; - -void free_unless_used(void *refcon, reg_t addr) { - deallocator_t *deallocator = (deallocator_t *)refcon; - reg_t_hash_map *use_map = deallocator->use_map; - - if (!use_map->contains(addr)) { - // Not found -> we can free it - deallocator->mobj->freeAtAddress(deallocator->segMan, addr); -#ifdef DEBUG_GC - debugC(2, kDebugLevelGC, "[GC] Deallocating %04x:%04x", PRINT_REG(addr)); - deallocator->segcount[deallocator->mobj->getType()]++; -#endif - } - -} - void run_gc(EngineState *s) { - uint seg_nr; - deallocator_t deallocator; SegManager *segMan = s->_segMan; -#ifdef DEBUG_GC + // Some debug stuff debugC(2, kDebugLevelGC, "[GC] Running..."); - memset(&(deallocator.segcount), 0, sizeof(int) * (SEG_TYPE_MAX + 1)); -#endif - - deallocator.segMan = segMan; - deallocator.use_map = find_all_used_references(s); - - for (seg_nr = 1; seg_nr < segMan->_heap.size(); seg_nr++) { - if (segMan->_heap[seg_nr] != NULL) { - deallocator.mobj = segMan->_heap[seg_nr]; -#ifdef DEBUG_GC - deallocator.segnames[deallocator.mobj->getType()] = deallocator.mobj->type; // FIXME: add a segment "name" -#endif - deallocator.mobj->listAllDeallocatable(seg_nr, &deallocator, free_unless_used); + const char *segnames[SEG_TYPE_MAX + 1]; + int segcount[SEG_TYPE_MAX + 1]; + memset(segnames, 0, sizeof(segnames)); + memset(segcount, 0, sizeof(segcount)); + + // Compute the set of all segments references currently in use. + AddrSet *activeRefs = findAllActiveReferences(s); + + // Iterate over all segments, and check for each whether it + // contains stuff that can be collected. + const Common::Array<SegmentObj *> &heap = segMan->getSegments(); + for (uint seg = 1; seg < heap.size(); seg++) { + SegmentObj *mobj = heap[seg]; + if (mobj != NULL) { + const SegmentType type = mobj->getType(); + segnames[type] = SegmentObj::getSegmentTypeName(type); + + // Get a list of all deallocatable objects in this segment, + // then free any which are not referenced from somewhere. + const Common::Array<reg_t> tmp = mobj->listAllDeallocatable(seg); + for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) { + const reg_t addr = *it; + if (!activeRefs->contains(addr)) { + // Not found -> we can free it + mobj->freeAtAddress(segMan, addr); + debugC(2, kDebugLevelGC, "[GC] Deallocating %04x:%04x", PRINT_REG(addr)); + segcount[type]++; + } + } + } } - delete deallocator.use_map; + delete activeRefs; -#ifdef DEBUG_GC - { - int i; - debugC(2, kDebugLevelGC, "[GC] Summary:"); - for (i = 0; i <= SEG_TYPE_MAX; i++) - if (deallocator.segcount[i]) - debugC(2, kDebugLevelGC, "\t%d\t* %s", deallocator.segcount[i], deallocator.segnames[i]); - } -#endif + // Output debug summary of garbage collection + debugC(2, kDebugLevelGC, "[GC] Summary:"); + for (int i = 0; i <= SEG_TYPE_MAX; i++) + if (segcount[i]) + debugC(2, kDebugLevelGC, "\t%d\t* %s", segcount[i], segnames[i]); } } // End of namespace Sci diff --git a/engines/sci/engine/gc.h b/engines/sci/engine/gc.h index 9f9347ca18..f4318a1453 100644 --- a/engines/sci/engine/gc.h +++ b/engines/sci/engine/gc.h @@ -33,29 +33,24 @@ namespace Sci { -struct reg_t_EqualTo { - bool operator()(const reg_t& x, const reg_t& y) const { - return (x.segment == y.segment) && (x.offset == y.offset); - } -}; - struct reg_t_Hash { uint operator()(const reg_t& x) const { - return (x.segment << 3) | x.offset; + return (x.segment << 3) ^ x.offset ^ (x.offset << 16); } }; /* - * The reg_t_hash_map is actually really a hashset + * The AddrSet is a "set" of reg_t values. + * We don't have a HashSet type, so we abuse a HashMap for this. */ -typedef Common::HashMap<reg_t, bool, reg_t_Hash, reg_t_EqualTo> reg_t_hash_map; +typedef Common::HashMap<reg_t, bool, reg_t_Hash> AddrSet; /** * Finds all used references and normalises them to their memory addresses * @param s The state to gather all information from * @return A hash map containing entries for all used references */ -reg_t_hash_map *find_all_used_references(EngineState *s); +AddrSet *findAllActiveReferences(EngineState *s); /** * Runs garbage collection on the current system state diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 6ebee2dfbd..beb1d3ce35 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -33,10 +33,28 @@ namespace Sci { -// Default kernel name table -#define SCI_KNAMES_DEFAULT_ENTRIES_NR 0x89 - -static const char *sci_default_knames[SCI_KNAMES_DEFAULT_ENTRIES_NR] = { +// Uncompiled kernel signatures are formed from a string of letters. +// each corresponding to a type of a parameter (see below). +// Use small letters to indicate end of sum type. +// Use capital letters for sum types, e.g. +// "LNoLr" for a function which takes two arguments: +// (1) list, node or object +// (2) list or ref +#define KSIG_SPEC_LIST 'l' +#define KSIG_SPEC_NODE 'n' +#define KSIG_SPEC_OBJECT 'o' +#define KSIG_SPEC_REF 'r' // Said Specs and strings +#define KSIG_SPEC_ARITHMETIC 'i' +#define KSIG_SPEC_NULL 'z' +#define KSIG_SPEC_ANY '.' +#define KSIG_SPEC_ELLIPSIS '*' // Arbitrarily more TYPED arguments + +#define KSIG_SPEC_SUM_DONE ('a' - 'A') + + + +/** Default kernel name table. */ +static const char *s_defaultKernelNames[] = { /*0x00*/ "Load", /*0x01*/ "UnLoad", /*0x02*/ "ScriptID", @@ -152,18 +170,18 @@ static const char *sci_default_knames[SCI_KNAMES_DEFAULT_ENTRIES_NR] = { /*0x6c*/ "Graph", /*0x6d*/ "Joystick", // End of kernel function table for SCI0 - /*0x6e*/ "ShiftScreen", + /*0x6e*/ "Dummy", // ShiftScreen /*0x6f*/ "Palette", /*0x70*/ "MemorySegment", /*0x71*/ "Intersections", // MoveCursor (SCI1 late), PalVary (SCI1.1) /*0x72*/ "Memory", - /*0x73*/ "ListOps", + /*0x73*/ "Dummy", // ListOps /*0x74*/ "FileIO", /*0x75*/ "DoAudio", /*0x76*/ "DoSync", /*0x77*/ "AvoidPath", /*0x78*/ "Sort", // StrSplit (SCI01) - /*0x79*/ "ATan", + /*0x79*/ "Dummy", // ATan /*0x7a*/ "Lock", /*0x7b*/ "StrSplit", /*0x7c*/ "GetMessage", // Message (SCI1.1) @@ -181,227 +199,456 @@ static const char *sci_default_knames[SCI_KNAMES_DEFAULT_ENTRIES_NR] = { /*0x88*/ "Dummy" // DbugStr }; -struct SciKernelFunction { +reg_t kStub(EngineState *s, int argc, reg_t *argv) { + Kernel *kernel = g_sci->getKernel(); + int kernelCallNr = -1; + + Common::List<ExecStack>::iterator callIterator = s->_executionStack.end(); + if (callIterator != s->_executionStack.begin()) { + callIterator--; + ExecStack lastCall = *callIterator; + kernelCallNr = lastCall.debugSelector; + } + + Common::String warningMsg = "Dummy function k" + kernel->getKernelName(kernelCallNr) + + Common::String::printf("[%x]", kernelCallNr) + + " invoked. Params: " + + Common::String::printf("%d", argc) + " ("; + + for (int i = 0; i < argc; i++) { + warningMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i])); + warningMsg += (i == argc - 1 ? ")" : ", "); + } + + warning("%s", warningMsg.c_str()); + return s->r_acc; +} + +reg_t kStubNull(EngineState *s, int argc, reg_t *argv) { + kStub(s, argc, argv); + return NULL_REG; +} + +reg_t kDummy(EngineState *s, int argc, reg_t *argv) { + kStub(s, argc, argv); + error("Kernel function was called, which was considered to be unused - see log for details"); +} + +// [io] -> either integer or object +// (io) -> optionally integer AND an object +// (i) -> optional integer +// . -> any type +// i* -> optional multiple integers +// .* -> any parameters afterwards (or none) + +// gameID, scriptNr,lvl, object-name, method-name, call, index, replace +static const SciWorkaroundEntry kAbs_workarounds[] = { + { GID_HOYLE1, 1, 0, "room1", "doit", -1, 0, { 2, 0x3e9 } }, // crazy eights - called with objects instead of integers + { GID_HOYLE1, 2, 0, "room2", "doit", -1, 0, { 2, 0x3e9 } }, // old maid - called with objects instead of integers + { GID_HOYLE1, 3, 0, "room3", "doit", -1, 0, { 2, 0x3e9 } }, // hearts - called with objects instead of integers + SCI_WORKAROUNDENTRY_TERMINATOR +}; + +// gameID, scriptNr,lvl, object-name, method-name, call, index, replace +static const SciWorkaroundEntry kDisposeScript_workarounds[] = { + { GID_QFG1, 64, 0, "rm64", "dispose", -1, 0, { 1, 0 } }, // when leaving graveyard, parameter 0 is an object + SCI_WORKAROUNDENTRY_TERMINATOR +}; + +// gameID, scriptNr,lvl, object-name, method-name, call, index, replace +static const SciWorkaroundEntry kDoSoundFade_workarounds[] = { + { GID_KQ6, 989, 0, "globalSound", "fade", -1, 0, { 0, 0 } }, // during intro, parameter 4 is an object + SCI_WORKAROUNDENTRY_TERMINATOR +}; + +// gameID, scriptNr,lvl, object-name, method-name, call, index, replace +static const SciWorkaroundEntry kGraphRestoreBox_workarounds[] = { + { GID_LSL6, 85, 0, "rScroller", "hide", -1, 0, { 0, 0 } }, // happens when restoring (sometimes), same as the one below + { GID_LSL6, 85, 0, "lScroller", "hide", -1, 0, { 0, 0 } }, // happens when restoring (sometimes), same as the one below + { GID_LSL6, 86, 0, "LL6Inv", "show", -1, 0, { 0, 0 } }, // happens when restoring, is called with hunk segment, but hunk is not allocated at that time + // ^^ TODO: check, if this is really a script error or an issue with our restore code + { GID_LSL6, 86, 0, "LL6Inv", "hide", -1, 0, { 0, 0 } }, // happens during the game, gets called with 1 extra parameter + SCI_WORKAROUNDENTRY_TERMINATOR +}; + +// gameID, scriptNr,lvl, object-name, method-name, call, index, replace +static const SciWorkaroundEntry kGraphFillBoxForeground_workarounds[] = { + { GID_LSL6, 0, 0, "LSL6", "hideControls", -1, 0, { 0, 0 } }, // happens when giving the bungee key to merrily - gets called with additional 5th parameter + SCI_WORKAROUNDENTRY_TERMINATOR +}; + +// gameID, scriptNr,lvl, object-name, method-name, call, index, replace +static const SciWorkaroundEntry kGraphFillBoxAny_workarounds[] = { + { GID_SQ4, 818, 0, "iconTextSwitch", "show", -1, 0, { 0, 0 } }, // game menu "text/speech" display - parameter 5 is missing, but the right color number is on the stack + SCI_WORKAROUNDENTRY_TERMINATOR +}; + +// gameID, scriptNr,lvl, object-name, method-name, call, index, replace +static const SciWorkaroundEntry kUnLoad_workarounds[] = { + { GID_LSL6, 130, 0, "recruitLarryScr", "changeState", -1, 0, { 1, 0 } }, // during intro, a 3rd parameter is passed by accident + { GID_LSL6, 740, 0, "showCartoon", "changeState", -1, 0, { 1, 0 } }, // during ending, 4 additional parameters are passed by accident + { GID_SQ1, 303, 0, "slotGuy", "dispose", -1, 0, { 1, 0 } }, // when leaving ulence flats bar, parameter 1 is not passed - script error + SCI_WORKAROUNDENTRY_TERMINATOR +}; + +struct SciKernelMapSubEntry { + SciVersion fromVersion; + SciVersion toVersion; + + uint16 id; + const char *name; - KernelFunc *fun; /* The actual function */ - const char *signature; /* kfunct signature */ + KernelFunctionCall *function; + + const char *signature; + const SciWorkaroundEntry *workarounds; +}; + +#define SCI_SUBOPENTRY_TERMINATOR { SCI_VERSION_NONE, SCI_VERSION_NONE, 0, NULL, NULL, NULL, NULL } + + +#define SIG_SCIALL SCI_VERSION_NONE, SCI_VERSION_NONE +#define SIG_SCI0 SCI_VERSION_NONE, SCI_VERSION_01 +#define SIG_SCI1 SCI_VERSION_1_EGA, SCI_VERSION_1_LATE +#define SIG_SCI11 SCI_VERSION_1_1, SCI_VERSION_1_1 +#define SIG_SCI16 SCI_VERSION_NONE, SCI_VERSION_1_1 +#define SIG_SCI32 SCI_VERSION_2, SCI_VERSION_NONE + +// SCI-Sound-Version +#define SIG_SOUNDSCI0 SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE +#define SIG_SOUNDSCI1EARLY SCI_VERSION_1_EARLY, SCI_VERSION_1_EARLY +#define SIG_SOUNDSCI1LATE SCI_VERSION_1_LATE, SCI_VERSION_1_LATE + +#define SIGFOR_ALL 0x3f +#define SIGFOR_DOS 1 << 0 +#define SIGFOR_PC98 1 << 1 +#define SIGFOR_WIN 1 << 2 +#define SIGFOR_MAC 1 << 3 +#define SIGFOR_AMIGA 1 << 4 +#define SIGFOR_ATARI 1 << 5 +#define SIGFOR_PC SIGFOR_DOS|SIGFOR_WIN + +#define SIG_EVERYWHERE SIG_SCIALL, SIGFOR_ALL + +#define MAP_CALL(_name_) #_name_, k##_name_ + +// version, subId, function-mapping, signature, workarounds +static const SciKernelMapSubEntry kDoSound_subops[] = { + { SIG_SOUNDSCI0, 0, MAP_CALL(DoSoundInit), "o", NULL }, + { SIG_SOUNDSCI0, 1, MAP_CALL(DoSoundPlay), "o", NULL }, + { SIG_SOUNDSCI0, 2, MAP_CALL(DoSoundDummy), "o", NULL }, + { SIG_SOUNDSCI0, 3, MAP_CALL(DoSoundDispose), "o", NULL }, + { SIG_SOUNDSCI0, 4, MAP_CALL(DoSoundMute), "(i)", NULL }, + { SIG_SOUNDSCI0, 5, MAP_CALL(DoSoundStop), "o", NULL }, + { SIG_SOUNDSCI0, 6, MAP_CALL(DoSoundPause), "i", NULL }, + { SIG_SOUNDSCI0, 7, MAP_CALL(DoSoundResume), "", NULL }, + { SIG_SOUNDSCI0, 8, MAP_CALL(DoSoundMasterVolume), "(i)", NULL }, + { SIG_SOUNDSCI0, 9, MAP_CALL(DoSoundUpdate), "o", NULL }, + { SIG_SOUNDSCI0, 10, MAP_CALL(DoSoundFade), "o", NULL }, + { SIG_SOUNDSCI0, 11, MAP_CALL(DoSoundGetPolyphony), "", NULL }, + { SIG_SOUNDSCI0, 12, MAP_CALL(DoSoundStopAll), "", NULL }, + { SIG_SOUNDSCI1EARLY, 0, MAP_CALL(DoSoundMasterVolume), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 1, MAP_CALL(DoSoundMute), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 2, MAP_CALL(DoSoundDummy), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 3, MAP_CALL(DoSoundGetPolyphony), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 4, MAP_CALL(DoSoundUpdate), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 5, MAP_CALL(DoSoundInit), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 6, MAP_CALL(DoSoundDispose), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 7, MAP_CALL(DoSoundPlay), "oi", NULL }, + { SIG_SOUNDSCI1EARLY, 8, MAP_CALL(DoSoundStop), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 9, MAP_CALL(DoSoundPause), "[o0]i", NULL }, + { SIG_SOUNDSCI1EARLY, 10, MAP_CALL(DoSoundFade), "oiiii", NULL }, + { SIG_SOUNDSCI1EARLY, 11, MAP_CALL(DoSoundUpdateCues), "o", NULL }, + { SIG_SOUNDSCI1EARLY, 12, MAP_CALL(DoSoundSendMidi), "oiiii", NULL }, + { SIG_SOUNDSCI1EARLY, 13, MAP_CALL(DoSoundReverb), "oi", NULL }, + { SIG_SOUNDSCI1EARLY, 14, MAP_CALL(DoSoundSetHold), "oi", NULL }, + { SIG_SOUNDSCI1EARLY, 15, MAP_CALL(DoSoundDummy), "", NULL }, + // ^^ Longbow demo + { SIG_SOUNDSCI1LATE, 0, MAP_CALL(DoSoundMasterVolume), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 1, MAP_CALL(DoSoundMute), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 2, MAP_CALL(DoSoundDummy), "", NULL }, + { SIG_SOUNDSCI1LATE, 3, MAP_CALL(DoSoundGetPolyphony), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 4, MAP_CALL(DoSoundGetAudioCapability), "", NULL }, + { SIG_SOUNDSCI1LATE, 5, MAP_CALL(DoSoundSuspend), "i", NULL }, + { SIG_SOUNDSCI1LATE, 6, MAP_CALL(DoSoundInit), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 7, MAP_CALL(DoSoundDispose), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 8, MAP_CALL(DoSoundPlay), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 9, MAP_CALL(DoSoundStop), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 10, MAP_CALL(DoSoundPause), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 11, MAP_CALL(DoSoundFade), "oiiii(i)", kDoSoundFade_workarounds }, + { SIG_SOUNDSCI1LATE, 12, MAP_CALL(DoSoundSetHold), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 13, MAP_CALL(DoSoundDummy), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 14, MAP_CALL(DoSoundSetVolume), "oi", NULL }, + { SIG_SOUNDSCI1LATE, 15, MAP_CALL(DoSoundSetPriority), "oi", NULL }, + { SIG_SOUNDSCI1LATE, 16, MAP_CALL(DoSoundSetLoop), "oi", NULL }, + { SIG_SOUNDSCI1LATE, 17, MAP_CALL(DoSoundUpdateCues), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 18, MAP_CALL(DoSoundSendMidi), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 19, MAP_CALL(DoSoundReverb), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 20, MAP_CALL(DoSoundUpdate), NULL, NULL }, + SCI_SUBOPENTRY_TERMINATOR }; -#define DEFUN(name, fun, sig) {name, fun, sig} - -SciKernelFunction kfunct_mappers[] = { - /*00*/ DEFUN("Load", kLoad, "iii*"), - /*01*/ DEFUN("UnLoad", kUnLoad, "i.*"), // Work around SQ1 bug, when exiting the Ulence flats bar - /*02*/ DEFUN("ScriptID", kScriptID, "Ioi*"), - /*03*/ DEFUN("DisposeScript", kDisposeScript, "Oii*"), // Work around QfG1 bug - /*04*/ DEFUN("Clone", kClone, "o"), - /*05*/ DEFUN("DisposeClone", kDisposeClone, "o"), - /*06*/ DEFUN("IsObject", kIsObject, "."), - /*07*/ DEFUN("RespondsTo", kRespondsTo, ".i"), - /*08*/ DEFUN("DrawPic", kDrawPic, "i*"), - - /*0a*/ DEFUN("PicNotValid", kPicNotValid, "i*"), - /*0b*/ DEFUN("Animate", kAnimate, "LI*"), // More like (li?)? - /*0c*/ DEFUN("SetNowSeen", kSetNowSeen, "oi*"), // The second parameter is ignored - /*0d*/ DEFUN("NumLoops", kNumLoops, "o"), - /*0e*/ DEFUN("NumCels", kNumCels, "o"), - /*0f*/ DEFUN("CelWide", kCelWide, "iOi*"), - /*10*/ DEFUN("CelHigh", kCelHigh, "iOi*"), - /*11*/ DEFUN("DrawCel", kDrawCel, "iiiiii*i*r*"), - /*12*/ DEFUN("AddToPic", kAddToPic, "Il*"), - // FIXME: signature check removed (set to .*) as kNewWindow is different in Mac versions - /*13*/ DEFUN("NewWindow", kNewWindow, "*."), - ///*13*/ DEFUN("NewWindow", kNewWindow, "iiiiZRi*"), - /*14*/ DEFUN("GetPort", kGetPort, ""), - /*15*/ DEFUN("SetPort", kSetPort, "ii*"), - /*16*/ DEFUN("DisposeWindow", kDisposeWindow, "ii*"), - /*17*/ DEFUN("DrawControl", kDrawControl, "o"), - /*18*/ DEFUN("HiliteControl", kHiliteControl, "o"), - /*19*/ DEFUN("EditControl", kEditControl, "ZoZo"), - /*1a*/ DEFUN("TextSize", kTextSize, "rZrii*r*"), - /*1b*/ DEFUN("Display", kDisplay, ".*"), - /*1c*/ DEFUN("GetEvent", kGetEvent, "ioi*"), // Mac versions pass an extra 3rd parameter (ignored - always 0?) - /*1d*/ DEFUN("GlobalToLocal", kGlobalToLocal, "oo*"), - /*1e*/ DEFUN("LocalToGlobal", kLocalToGlobal, "oo*"), - /*1f*/ DEFUN("MapKeyToDir", kMapKeyToDir, "o"), - /*20*/ DEFUN("DrawMenuBar", kDrawMenuBar, "i"), - /*21*/ DEFUN("MenuSelect", kMenuSelect, "oi*"), - /*22*/ DEFUN("AddMenu", kAddMenu, "rr"), - /*23*/ DEFUN("DrawStatus", kDrawStatus, "Zri*"), - /*24*/ DEFUN("Parse", kParse, "ro"), - /*25*/ DEFUN("Said", kSaid, "Zr"), - /*26*/ DEFUN("SetSynonyms", kSetSynonyms, "o"), - /*27*/ DEFUN("HaveMouse", kHaveMouse, ""), - /*28*/ DEFUN("SetCursor", kSetCursor, "i*"), - // FIXME: The number 0x28 occurs twice :-) - /*28*/ DEFUN("MoveCursor", kMoveCursor, "ii"), - /*29*/ DEFUN("FOpen", kFOpen, "ri"), - /*2a*/ DEFUN("FPuts", kFPuts, "ir"), - /*2b*/ DEFUN("FGets", kFGets, "rii"), - /*2c*/ DEFUN("FClose", kFClose, "i"), - /*2d*/ DEFUN("SaveGame", kSaveGame, "rirr*"), - /*2e*/ DEFUN("RestoreGame", kRestoreGame, "rir*"), - /*2f*/ DEFUN("RestartGame", kRestartGame, ""), - /*30*/ DEFUN("GameIsRestarting", kGameIsRestarting, "i*"), - /*31*/ DEFUN("DoSound", kDoSound, "iIo*"), - /*32*/ DEFUN("NewList", kNewList, ""), - /*33*/ DEFUN("DisposeList", kDisposeList, "l"), - /*34*/ DEFUN("NewNode", kNewNode, ".."), - /*35*/ DEFUN("FirstNode", kFirstNode, "Zl"), - /*36*/ DEFUN("LastNode", kLastNode, "l"), - /*37*/ DEFUN("EmptyList", kEmptyList, "l"), - /*38*/ DEFUN("NextNode", kNextNode, "n"), - /*39*/ DEFUN("PrevNode", kPrevNode, "n"), - /*3a*/ DEFUN("NodeValue", kNodeValue, "Zn"), - /*3b*/ DEFUN("AddAfter", kAddAfter, "lnn"), - /*3c*/ DEFUN("AddToFront", kAddToFront, "ln"), - /*3d*/ DEFUN("AddToEnd", kAddToEnd, "ln"), - /*3e*/ DEFUN("FindKey", kFindKey, "l."), - /*3f*/ DEFUN("DeleteKey", kDeleteKey, "l."), - /*40*/ DEFUN("Random", kRandom, "i*"), - /*41*/ DEFUN("Abs", kAbs, "Oi"), - /*42*/ DEFUN("Sqrt", kSqrt, "i"), - /*43*/ DEFUN("GetAngle", kGetAngle, "iiiii*"), // occasionally KQ6 passes a 5th argument by mistake - /*44*/ DEFUN("GetDistance", kGetDistance, "iiiii*"), - /*45*/ DEFUN("Wait", kWait, "i"), - /*46*/ DEFUN("GetTime", kGetTime, "i*"), - /*47*/ DEFUN("StrEnd", kStrEnd, "r"), - /*48*/ DEFUN("StrCat", kStrCat, "rr"), - /*49*/ DEFUN("StrCmp", kStrCmp, "rri*"), - /*4a*/ DEFUN("StrLen", kStrLen, "Zr"), - /*4b*/ DEFUN("StrCpy", kStrCpy, "rZri*"), - /*4c*/ DEFUN("Format", kFormat, "r.*"), - /*4d*/ DEFUN("GetFarText", kGetFarText, "iiZr"), - /*4e*/ DEFUN("ReadNumber", kReadNumber, "r"), - /*4f*/ DEFUN("BaseSetter", kBaseSetter, "o"), - /*50*/ DEFUN("DirLoop", kDirLoop, "oi"), - // Opcode 51 is defined twice for a reason: In older SCI versions - // it is CanBeHere, whereas in newer version it is CantBeHere - /*51*/ DEFUN("CanBeHere", kCanBeHere, "ol*"), - /*51*/ DEFUN("CantBeHere", kCantBeHere, "ol*"), - /*52*/ DEFUN("OnControl", kOnControl, "i*"), - /*53*/ DEFUN("InitBresen", kInitBresen, "oi*"), - /*54*/ DEFUN("DoBresen", kDoBresen, "o"), - /*55*/ DEFUN("DoAvoider", kDoAvoider, "o"), - /*56*/ DEFUN("SetJump", kSetJump, "oiii"), - /*57*/ DEFUN("SetDebug", kSetDebug, "i*"), - /*5c*/ DEFUN("MemoryInfo", kMemoryInfo, "i"), - /*5f*/ DEFUN("GetMenu", kGetMenu, "i."), - /*60*/ DEFUN("SetMenu", kSetMenu, "i.*"), - /*61*/ DEFUN("GetSaveFiles", kGetSaveFiles, "rrr"), - /*62*/ DEFUN("GetCWD", kGetCWD, "r"), - /*63*/ DEFUN("CheckFreeSpace", kCheckFreeSpace, "r.*"), - /*64*/ DEFUN("ValidPath", kValidPath, "r"), - /*65*/ DEFUN("CoordPri", kCoordPri, "ii*"), - /*66*/ DEFUN("StrAt", kStrAt, "rii*"), - /*67*/ DEFUN("DeviceInfo", kDeviceInfo, "i.*"), - /*68*/ DEFUN("GetSaveDir", kGetSaveDir, ".*"), // accepts a parameter in SCI2+ games - /*69*/ DEFUN("CheckSaveGame", kCheckSaveGame, ".*"), - /*6a*/ DEFUN("ShakeScreen", kShakeScreen, "ii*"), - /*6b*/ DEFUN("FlushResources", kFlushResources, "i"), - /*6c*/ DEFUN("TimesSin", kTimesSin, "ii"), - /*6d*/ DEFUN("TimesCos", kTimesCos, "ii"), - /*6e*/ DEFUN("6e", kTimesSin, "ii"), - /*6f*/ DEFUN("6f", kTimesCos, "ii"), - /*70*/ DEFUN("Graph", kGraph, ".*"), - /*71*/ DEFUN("Joystick", kJoystick, ".*"), - - // Experimental functions - /*74*/ DEFUN("FileIO", kFileIO, "i.*"), - /*(?)*/ DEFUN("Memory", kMemory, "i.*"), - /*(?)*/ DEFUN("Sort", kSort, "ooo"), - /*(?)*/ DEFUN("AvoidPath", kAvoidPath, "ii.*"), - /*(?)*/ DEFUN("Lock", kLock, "iii*"), - /*(?)*/ DEFUN("Palette", kPalette, "i.*"), - /*(?)*/ DEFUN("IsItSkip", kIsItSkip, "iiiii"), - /*7b*/ DEFUN("StrSplit", kStrSplit, "rrZr"), - - // Non-experimental functions without a fixed ID - DEFUN("CosMult", kTimesCos, "ii"), - DEFUN("SinMult", kTimesSin, "ii"), - - // Misc functions - /*(?)*/ DEFUN("CosDiv", kCosDiv, "ii"), - /*(?)*/ DEFUN("PriCoord", kPriCoord, "i"), - /*(?)*/ DEFUN("SinDiv", kSinDiv, "ii"), - /*(?)*/ DEFUN("TimesCot", kTimesCot, "ii"), - /*(?)*/ DEFUN("TimesTan", kTimesTan, "ii"), - DEFUN("Message", kMessage, ".*"), - DEFUN("GetMessage", kGetMessage, "iiir"), - DEFUN("DoAudio", kDoAudio, ".*"), - DEFUN("DoSync", kDoSync, ".*"), - DEFUN("MemorySegment", kMemorySegment, "iri*"), - DEFUN("Intersections", kIntersections, "iiiiriiiri"), - DEFUN("MergePoly", kMergePoly, "rli"), - DEFUN("ResCheck", kResCheck, "iii*"), - DEFUN("SetQuitStr", kSetQuitStr, "r"), - DEFUN("ShowMovie", kShowMovie, ".*"), - DEFUN("SetVideoMode", kSetVideoMode, "i"), - DEFUN("Platform", kPlatform, ".*"), - DEFUN("TextColors", kTextColors, ".*"), - DEFUN("TextFonts", kTextFonts, ".*"), - DEFUN("Portrait", kPortrait, ".*"), +// version, subId, function-mapping, signature, workarounds +static const SciKernelMapSubEntry kGraph_subops[] = { + { SIG_SCI32, 1, MAP_CALL(StubNull), "", NULL }, // called by gk1 sci32 right at the start + { SIG_SCIALL, 2, MAP_CALL(GraphGetColorCount), "", NULL }, + // 3 - set palette via resource + { SIG_SCIALL, 4, MAP_CALL(GraphDrawLine), "iiiii(i)(i)", NULL }, + // 5 - nop + // 6 - draw pattern + { SIG_SCIALL, 7, MAP_CALL(GraphSaveBox), "iiiii", NULL }, + { SIG_SCIALL, 8, MAP_CALL(GraphRestoreBox), "[r0!]", kGraphRestoreBox_workarounds }, + // ^ this may get called with invalid references, we check them within restoreBits() and sierra sci behaves the same + { SIG_SCIALL, 9, MAP_CALL(GraphFillBoxBackground), "iiii", NULL }, + { SIG_SCIALL, 10, MAP_CALL(GraphFillBoxForeground), "iiii", kGraphFillBoxForeground_workarounds }, + { SIG_SCIALL, 11, MAP_CALL(GraphFillBoxAny), "iiiiii(i)(i)", kGraphFillBoxAny_workarounds }, + { SIG_SCI11, 12, MAP_CALL(GraphUpdateBox), "iiii(i)(r0)", NULL }, // kq6 hires + { SIG_SCIALL, 12, MAP_CALL(GraphUpdateBox), "iiii(i)", NULL }, + { SIG_SCIALL, 13, MAP_CALL(GraphRedrawBox), "iiii", NULL }, + { SIG_SCIALL, 14, MAP_CALL(GraphAdjustPriority), "ii", NULL }, + { SIG_SCI11, 15, MAP_CALL(GraphSaveUpscaledHiresBox), "iiii", NULL }, // kq6 hires + SCI_SUBOPENTRY_TERMINATOR +}; -#ifdef ENABLE_SCI32 - // SCI2 Kernel Functions - DEFUN("IsHiRes", kIsHiRes, ""), - DEFUN("Array", kArray, ".*"), - DEFUN("ListAt", kListAt, "li"), - DEFUN("String", kString, ".*"), - DEFUN("AddScreenItem", kAddScreenItem, "o"), - DEFUN("UpdateScreenItem", kUpdateScreenItem, "o"), - DEFUN("DeleteScreenItem", kDeleteScreenItem, "o"), - DEFUN("AddPlane", kAddPlane, "o"), - DEFUN("DeletePlane", kDeletePlane, "o"), - DEFUN("UpdatePlane", kUpdatePlane, "o"), - DEFUN("RepaintPlane", kRepaintPlane, "o"), - DEFUN("GetHighPlanePri", kGetHighPlanePri, ""), - DEFUN("FrameOut", kFrameOut, ""), - DEFUN("ListEachElementDo", kListEachElementDo, "li.*"), - DEFUN("ListFirstTrue", kListFirstTrue, "li.*"), - DEFUN("ListAllTrue", kListAllTrue, "li.*"), - DEFUN("ListIndexOf", kListIndexOf, "lZo"), - DEFUN("OnMe", kOnMe, "iio.*"), - DEFUN("InPolygon", kInPolygon, "iio"), - DEFUN("CreateTextBitmap", kCreateTextBitmap, "i.*"), - - // SCI2.1 Kernel Functions - DEFUN("Save", kSave, ".*"), - DEFUN("List", kList, ".*"), - DEFUN("Robot", kRobot, ".*"), - DEFUN("IsOnMe", kOnMe, "iio.*"), // TODO: this seems right, but verify... +// version, subId, function-mapping, signature, workarounds +static const SciKernelMapSubEntry kPalVary_subops[] = { + { SIG_SCIALL, 0, MAP_CALL(PalVaryInit), "ii(i)(i)", NULL }, + { SIG_SCIALL, 1, MAP_CALL(PalVaryReverse), "(i)(i)(i)", NULL }, + { SIG_SCIALL, 2, MAP_CALL(PalVaryGetCurrentStep), "", NULL }, + { SIG_SCIALL, 3, MAP_CALL(PalVaryDeinit), "", NULL }, + { SIG_SCIALL, 4, MAP_CALL(PalVaryChangeTarget), "i", NULL }, + { SIG_SCIALL, 5, MAP_CALL(PalVaryChangeTicks), "i", NULL }, + { SIG_SCIALL, 6, MAP_CALL(PalVaryPauseResume), "i", NULL }, + { SIG_SCI32, 8, MAP_CALL(PalVaryUnknown), "", NULL }, + SCI_SUBOPENTRY_TERMINATOR +}; -#endif +// version, subId, function-mapping, signature, workarounds +static const SciKernelMapSubEntry kPalette_subops[] = { + { SIG_SCIALL, 1, MAP_CALL(PaletteSetFromResource), "i(i)", NULL }, + { SIG_SCIALL, 2, MAP_CALL(PaletteSetFlag), "iii", NULL }, + { SIG_SCIALL, 3, MAP_CALL(PaletteUnsetFlag), "iii", NULL }, + { SIG_SCIALL, 4, MAP_CALL(PaletteSetIntensity), "iii(i)", NULL }, + { SIG_SCIALL, 5, MAP_CALL(PaletteFindColor), "iii", NULL }, + { SIG_SCIALL, 6, MAP_CALL(PaletteAnimate), "i*", NULL }, + { SIG_SCIALL, 7, MAP_CALL(PaletteSave), "", NULL }, + { SIG_SCIALL, 8, MAP_CALL(PaletteRestore), "i", NULL }, + SCI_SUBOPENTRY_TERMINATOR +}; - // its a stub, but its needed for Pharkas to work - DEFUN("PalVary", kPalVary, "ii*"), - DEFUN("AssertPalette", kAssertPalette, "i"), - -#if 0 - // Stub functions - /*09*/ DEFUN("Show", kShow, "i"), - DEFUN("ShiftScreen", kShiftScreen, ".*"), - DEFUN("ListOps", kListOps, ".*"), - DEFUN("ATan", kATan, ".*"), - DEFUN("Record", kRecord, ".*"), - DEFUN("PlayBack", kPlayBack, ".*"), - DEFUN("DbugStr", kDbugStr, ".*"), -#endif +struct SciKernelMapEntry { + const char *name; + KernelFunctionCall *function; + + SciVersion fromVersion; + SciVersion toVersion; + byte forPlatform; + + const char *signature; + const SciKernelMapSubEntry *subFunctions; + const SciWorkaroundEntry *workarounds; +}; + +// name, version/platform, signature, sub-signatures, workarounds +static SciKernelMapEntry s_kernelMap[] = { + { MAP_CALL(Abs), SIG_EVERYWHERE, "i", NULL, kAbs_workarounds }, + { MAP_CALL(AddAfter), SIG_EVERYWHERE, "lnn", NULL, NULL }, + { MAP_CALL(AddMenu), SIG_EVERYWHERE, "rr", NULL, NULL }, + { MAP_CALL(AddToEnd), SIG_EVERYWHERE, "ln", NULL, NULL }, + { MAP_CALL(AddToFront), SIG_EVERYWHERE, "ln", NULL, NULL }, + { MAP_CALL(AddToPic), SIG_EVERYWHERE, "[il](iiiiii)", NULL, NULL }, + { MAP_CALL(Animate), SIG_EVERYWHERE, "(l0)(i)", NULL, NULL }, + { MAP_CALL(AssertPalette), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(AvoidPath), SIG_EVERYWHERE, "ii(.*)", NULL, NULL }, + { MAP_CALL(BaseSetter), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(CanBeHere), SIG_EVERYWHERE, "o(l)", NULL, NULL }, + { MAP_CALL(CantBeHere), SIG_EVERYWHERE, "o(l)", NULL, NULL }, + { MAP_CALL(CelHigh), SIG_EVERYWHERE, "ii(i)", NULL, NULL }, + { MAP_CALL(CelWide), SIG_EVERYWHERE, "ii(i)", NULL, NULL }, + { MAP_CALL(CheckFreeSpace), SIG_SCI32, SIGFOR_ALL, "r.*", NULL, NULL }, + { MAP_CALL(CheckFreeSpace), SIG_EVERYWHERE, "r", NULL, NULL }, + { MAP_CALL(CheckSaveGame), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(Clone), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(CoordPri), SIG_EVERYWHERE, "i(i)", NULL, NULL }, + { MAP_CALL(CosDiv), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(DeleteKey), SIG_EVERYWHERE, "l.", NULL, NULL }, + { MAP_CALL(DeviceInfo), SIG_EVERYWHERE, "i(r)(r)(i)", NULL, NULL }, // subop + { MAP_CALL(Display), SIG_EVERYWHERE, "[ir]([ir!]*)", NULL, NULL }, + // ^ we allow invalid references here, because kDisplay gets called with those in e.g. pq3 during intro + // restoreBits() checks and skips invalid handles, so that's fine. Sierra SCI behaved the same + { MAP_CALL(DirLoop), SIG_EVERYWHERE, "oi", NULL, NULL }, + { MAP_CALL(DisposeClone), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(DisposeList), SIG_EVERYWHERE, "l", NULL, NULL }, + { MAP_CALL(DisposeScript), SIG_EVERYWHERE, "i(i*)", NULL, kDisposeScript_workarounds }, + { MAP_CALL(DisposeWindow), SIG_EVERYWHERE, "i(i)", NULL, NULL }, + { MAP_CALL(DoAudio), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(DoAvoider), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(DoBresen), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(DoSound), SIG_EVERYWHERE, "i([io])(i)(ii[io])(i)", kDoSound_subops, NULL }, + { MAP_CALL(DoSync), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(DrawCel), SIG_SCI11, SIGFOR_PC, "iiiii(i)(i)(r0)", NULL, NULL }, // for kq6 hires + { MAP_CALL(DrawCel), SIG_EVERYWHERE, "iiiii(i)(i)", NULL, NULL }, + { MAP_CALL(DrawControl), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(DrawMenuBar), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(DrawPic), SIG_EVERYWHERE, "i(i)(i)(i)", NULL, NULL }, + { MAP_CALL(DrawStatus), SIG_EVERYWHERE, "[r0](i)(i)", NULL, NULL }, + { MAP_CALL(EditControl), SIG_EVERYWHERE, "[o0][o0]", NULL, NULL }, + { MAP_CALL(Empty), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(EmptyList), SIG_EVERYWHERE, "l", NULL, NULL }, + { MAP_CALL(FClose), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(FGets), SIG_EVERYWHERE, "rii", NULL, NULL }, + { MAP_CALL(FOpen), SIG_EVERYWHERE, "ri", NULL, NULL }, + { MAP_CALL(FPuts), SIG_EVERYWHERE, "ir", NULL, NULL }, + { MAP_CALL(FileIO), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(FindKey), SIG_EVERYWHERE, "l.", NULL, NULL }, + { MAP_CALL(FirstNode), SIG_EVERYWHERE, "[l0]", NULL, NULL }, + { MAP_CALL(FlushResources), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(Format), SIG_EVERYWHERE, "r(.*)", NULL, NULL }, + { MAP_CALL(GameIsRestarting), SIG_EVERYWHERE, "(i)", NULL, NULL }, + { MAP_CALL(GetAngle), SIG_EVERYWHERE, "iiii", NULL, NULL }, + // ^^ FIXME - occasionally KQ6 passes a 5th argument by mistake + { MAP_CALL(GetCWD), SIG_EVERYWHERE, "r", NULL, NULL }, + { MAP_CALL(GetDistance), SIG_EVERYWHERE, "ii(i)(i)(i)(i)", NULL, NULL }, + { MAP_CALL(GetEvent), SIG_SCIALL, SIGFOR_MAC, "io(i*)", NULL, NULL }, + { MAP_CALL(GetEvent), SIG_EVERYWHERE, "io", NULL, NULL }, + { MAP_CALL(GetFarText), SIG_EVERYWHERE, "ii[r0]", NULL, NULL }, + { MAP_CALL(GetMenu), SIG_EVERYWHERE, "i.", NULL, NULL }, + { MAP_CALL(GetMessage), SIG_EVERYWHERE, "iiir", NULL, NULL }, + { MAP_CALL(GetPort), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(GetSaveDir), SIG_SCI32, SIGFOR_ALL, "(r*)", NULL, NULL }, + { MAP_CALL(GetSaveDir), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(GetSaveFiles), SIG_EVERYWHERE, "rrr", NULL, NULL }, + { MAP_CALL(GetTime), SIG_EVERYWHERE, "(i)", NULL, NULL }, + { MAP_CALL(GlobalToLocal), SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL }, + { MAP_CALL(GlobalToLocal), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(Graph), SIG_EVERYWHERE, NULL, kGraph_subops, NULL }, + { MAP_CALL(HaveMouse), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(HiliteControl), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(InitBresen), SIG_EVERYWHERE, "o(i)", NULL, NULL }, + { MAP_CALL(Intersections), SIG_EVERYWHERE, "iiiiriiiri", NULL, NULL }, + { MAP_CALL(IsItSkip), SIG_EVERYWHERE, "iiiii", NULL, NULL }, + { MAP_CALL(IsObject), SIG_EVERYWHERE, ".", NULL, NULL }, + { MAP_CALL(Joystick), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(LastNode), SIG_EVERYWHERE, "l", NULL, NULL }, + { MAP_CALL(Load), SIG_EVERYWHERE, "ii(i*)", NULL, NULL }, + { MAP_CALL(LocalToGlobal), SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL }, + { MAP_CALL(LocalToGlobal), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(Lock), SIG_EVERYWHERE, "ii(i)", NULL, NULL }, + { MAP_CALL(MapKeyToDir), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(Memory), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(MemoryInfo), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(MemorySegment), SIG_EVERYWHERE, "ir(i)", NULL, NULL }, // subop + { MAP_CALL(MenuSelect), SIG_EVERYWHERE, "o(i)", NULL, NULL }, + { MAP_CALL(MergePoly), SIG_EVERYWHERE, "rli", NULL, NULL }, + { MAP_CALL(Message), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(MoveCursor), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(NewList), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(NewNode), SIG_EVERYWHERE, "..", NULL, NULL }, + { MAP_CALL(NewWindow), SIG_SCIALL, SIGFOR_MAC, ".*", NULL, NULL }, + { MAP_CALL(NewWindow), SIG_SCI0, SIGFOR_ALL, "iiii[r0]i(i)(i)(i)", NULL, NULL }, + { MAP_CALL(NewWindow), SIG_SCI1, SIGFOR_ALL, "iiii[ir]i(i)(i)([ir])(i)(i)(i)(i)", NULL, NULL }, + { MAP_CALL(NewWindow), SIG_SCI11, SIGFOR_ALL, "iiiiiiii[r0]i(i)(i)(i)", NULL, NULL }, + { MAP_CALL(NextNode), SIG_EVERYWHERE, "n", NULL, NULL }, + { MAP_CALL(NodeValue), SIG_EVERYWHERE, "[n0]", NULL, NULL }, + { MAP_CALL(NumCels), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(NumLoops), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(OnControl), SIG_EVERYWHERE, "ii(i)(i)(i)", NULL, NULL }, + { MAP_CALL(PalVary), SIG_EVERYWHERE, "i(i*)", kPalVary_subops, NULL }, + { MAP_CALL(Palette), SIG_EVERYWHERE, "i(.*)", kPalette_subops, NULL }, + { MAP_CALL(Parse), SIG_EVERYWHERE, "ro", NULL, NULL }, + { MAP_CALL(PicNotValid), SIG_EVERYWHERE, "(i)", NULL, NULL }, + { MAP_CALL(Platform), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(Portrait), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(PrevNode), SIG_EVERYWHERE, "n", NULL, NULL }, + { MAP_CALL(PriCoord), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(Random), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(ReadNumber), SIG_EVERYWHERE, "r", NULL, NULL }, + { MAP_CALL(ResCheck), SIG_EVERYWHERE, "ii(iiii)", NULL, NULL }, + { MAP_CALL(RespondsTo), SIG_EVERYWHERE, ".i", NULL, NULL }, + { MAP_CALL(RestartGame), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(RestoreGame), SIG_EVERYWHERE, "rir", NULL, NULL }, + { MAP_CALL(Said), SIG_EVERYWHERE, "[r0]", NULL, NULL }, + { MAP_CALL(SaveGame), SIG_EVERYWHERE, "rir(r)", NULL, NULL }, + { MAP_CALL(ScriptID), SIG_EVERYWHERE, "[io](i)", NULL, NULL }, + { MAP_CALL(SetCursor), SIG_EVERYWHERE, "i(i*)", NULL, NULL }, + { MAP_CALL(SetDebug), SIG_EVERYWHERE, "(i*)", NULL, NULL }, + { MAP_CALL(SetJump), SIG_EVERYWHERE, "oiii", NULL, NULL }, + { MAP_CALL(SetMenu), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, + { MAP_CALL(SetNowSeen), SIG_EVERYWHERE, "o(i)", NULL, NULL }, + { MAP_CALL(SetPort), SIG_EVERYWHERE, "i(iii)(i)(i)(i)", NULL, NULL }, + { MAP_CALL(SetQuitStr), SIG_EVERYWHERE, "r", NULL, NULL }, + { MAP_CALL(SetSynonyms), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(SetVideoMode), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(ShakeScreen), SIG_EVERYWHERE, "(i)(i)", NULL, NULL }, + { MAP_CALL(ShowMovie), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(SinDiv), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(Sort), SIG_EVERYWHERE, "ooo", NULL, NULL }, + { MAP_CALL(Sqrt), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(StrAt), SIG_EVERYWHERE, "ri(i)", NULL, NULL }, + { MAP_CALL(StrCat), SIG_EVERYWHERE, "rr", NULL, NULL }, + { MAP_CALL(StrCmp), SIG_EVERYWHERE, "rr(i)", NULL, NULL }, + { MAP_CALL(StrCpy), SIG_EVERYWHERE, "[r0]r(i)", NULL, NULL }, + { MAP_CALL(StrEnd), SIG_EVERYWHERE, "r", NULL, NULL }, + { MAP_CALL(StrLen), SIG_EVERYWHERE, "[r0]", NULL, NULL }, + { MAP_CALL(StrSplit), SIG_EVERYWHERE, "rr[r0]", NULL, NULL }, + { MAP_CALL(TextColors), SIG_EVERYWHERE, "(i*)", NULL, NULL }, + { MAP_CALL(TextFonts), SIG_EVERYWHERE, "(i*)", NULL, NULL }, + { MAP_CALL(TextSize), SIG_EVERYWHERE, "r[r0]i(i)(r0)", NULL, NULL }, + { MAP_CALL(TimesCos), SIG_EVERYWHERE, "ii", NULL, NULL }, + { "CosMult", kTimesCos, SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(TimesCot), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(TimesSin), SIG_EVERYWHERE, "ii", NULL, NULL }, + { "SinMult", kTimesSin, SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(TimesTan), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(UnLoad), SIG_EVERYWHERE, "i[ri]", NULL, kUnLoad_workarounds }, + { MAP_CALL(ValidPath), SIG_EVERYWHERE, "r", NULL, NULL }, + { MAP_CALL(Wait), SIG_EVERYWHERE, "i", NULL, NULL }, - {NULL, NULL, NULL} // Terminator +#ifdef ENABLE_SCI32 + // SCI2 Kernel Functions + { MAP_CALL(AddPlane), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(AddScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(Array), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(CreateTextBitmap), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, + { MAP_CALL(DeletePlane), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(DeleteScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(FrameOut), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(GetHighPlanePri), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(InPolygon), SIG_EVERYWHERE, "iio", NULL, NULL }, + { MAP_CALL(IsHiRes), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(ListAllTrue), SIG_EVERYWHERE, "li(.*)", NULL, NULL }, + { MAP_CALL(ListAt), SIG_EVERYWHERE, "li", NULL, NULL }, + { MAP_CALL(ListEachElementDo), SIG_EVERYWHERE, "li(.*)", NULL, NULL }, + { MAP_CALL(ListFirstTrue), SIG_EVERYWHERE, "li(.*)", NULL, NULL }, + { MAP_CALL(ListIndexOf), SIG_EVERYWHERE, "l[o0]", NULL, NULL }, + { MAP_CALL(OnMe), SIG_EVERYWHERE, "iio(.*)", NULL, NULL }, + { MAP_CALL(RepaintPlane), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(String), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(UpdatePlane), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(UpdateScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, + + // SCI2.1 Kernel Functions + { MAP_CALL(CD), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(IsOnMe), SIG_EVERYWHERE, "iio(.*)", NULL, NULL }, + { MAP_CALL(List), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(MulDiv), SIG_EVERYWHERE, "iii", NULL, NULL }, + { MAP_CALL(PlayVMD), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(Robot), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(Save), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(Text), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { NULL, NULL, SIG_EVERYWHERE, NULL, NULL, NULL } +#endif }; -Kernel::Kernel(ResourceManager *resMan, SegManager *segMan) : _resMan(resMan), _segMan(segMan) { +Kernel::Kernel(ResourceManager *resMan, SegManager *segMan) + : _resMan(resMan), _segMan(segMan), _invalid("<invalid>") { loadSelectorNames(); mapSelectors(); // Map a few special selectors for later use } Kernel::~Kernel() { - for (KernelFuncsContainer::iterator i = _kernelFuncs.begin(); i != _kernelFuncs.end(); ++i) - // TODO: Doing a const_cast is not that nice actually... But since KernelFuncWithSignature - // keeps the signature member as "const char *" there is no way around it. - // Think of a clever way to avoid this. - free(const_cast<char *>(i->signature)); + for (KernelFunctionArray::iterator i = _kernelFuncs.begin(); i != _kernelFuncs.end(); ++i) + free(i->signature); } uint Kernel::getSelectorNamesSize() const { @@ -409,6 +656,8 @@ uint Kernel::getSelectorNamesSize() const { } const Common::String &Kernel::getSelectorName(uint selector) const { + if (selector >= _selectorNames.size()) + return _invalid; return _selectorNames[selector]; } @@ -417,12 +666,10 @@ uint Kernel::getKernelNamesSize() const { } const Common::String &Kernel::getKernelName(uint number) const { - // FIXME: The following check is a temporary workaround for - // an issue leading to crashes when using the debugger's backtrace - // command. - static const Common::String invalid = "(invalid)"; + // FIXME: The following check is a temporary workaround for an issue + // leading to crashes when using the debugger's backtrace command. if (number >= _kernelNames.size()) - return invalid; + return _invalid; return _kernelNames[number]; } @@ -477,165 +724,241 @@ void Kernel::loadSelectorNames() { } } -static void kernel_compile_signature(const char **s) { - const char *src = *s; - char *result; - int ellipsis = 0; - char v; - int index = 0; - - if (!src) - return; // NULL signature: Nothing to do - - result = (char *)malloc(strlen(*s) + 1); - - while (*src) { - char c; - v = 0; - - if (ellipsis) { - error("Failed compiling kernel function signature '%s': non-terminal ellipsis '%c'", *s, *src); - } - - do { - char cc; - cc = c = *src++; - if (c >= 'A' || c <= 'Z') - cc = c | KSIG_SPEC_SUM_DONE; - - switch (cc) { - case KSIG_SPEC_LIST: - v |= KSIG_LIST; - break; - - case KSIG_SPEC_NODE: - v |= KSIG_NODE; - break; - - case KSIG_SPEC_REF: - v |= KSIG_REF; - break; - - case KSIG_SPEC_OBJECT: - v |= KSIG_OBJECT; - break; - - case KSIG_SPEC_ARITHMETIC: - v |= KSIG_ARITHMETIC; - break; - - case KSIG_SPEC_NULL: - v |= KSIG_NULL; - break; - - case KSIG_SPEC_ANY: - v |= KSIG_ANY; - break; - - case KSIG_SPEC_ELLIPSIS: - v |= KSIG_ELLIPSIS; - ellipsis = 1; - break; - - default: - error("INTERNAL ERROR when compiling kernel function signature '%s': (%02x) not understood (aka" - " '%c')\n", *s, c, c); +// this parses a written kernel signature into an internal memory format +// [io] -> either integer or object +// (io) -> optionally integer AND an object +// (i) -> optional integer +// . -> any type +// i* -> optional multiple integers +// .* -> any parameters afterwards (or none) +static uint16 *parseKernelSignature(const char *kernelName, const char *writtenSig) { + const char *curPos; + char curChar; + uint16 *result = NULL; + uint16 *writePos = NULL; + int size = 0; + bool validType = false; + bool optionalType = false; + bool eitherOr = false; + bool optional = false; + bool hadOptional = false; + + // No signature given? no signature out + if (!writtenSig) + return NULL; + + // First, we check how many bytes the result will be + // we also check, if the written signature makes any sense + curPos = writtenSig; + while (*curPos) { + curChar = *curPos; + switch (curChar) { + case '[': // either or + if (eitherOr) + error("signature for k%s: '[' used within '[]'", kernelName); + eitherOr = true; + validType = false; + break; + case ']': // either or end + if (!eitherOr) + error("signature for k%s: ']' used without leading '['", kernelName); + if (!validType) + error("signature for k%s: '[]' does not surround valid type(s)", kernelName); + eitherOr = false; + validType = false; + size++; + break; + case '(': // optional + if (optional) + error("signature for k%s: '(' used within '()' brackets", kernelName); + if (eitherOr) + error("signature for k%s: '(' used within '[]' brackets", kernelName); + optional = true; + validType = false; + optionalType = false; + break; + case ')': // optional end + if (!optional) + error("signature for k%s: ')' used without leading '('", kernelName); + if (!optionalType) + error("signature for k%s: '()' does not to surround valid type(s)", kernelName); + optional = false; + validType = false; + hadOptional = true; + break; + case '0': // allowed types + case 'i': + case 'o': + case 'r': + case 'l': + case 'n': + case '.': + case '!': + if ((hadOptional) & (!optional)) + error("signature for k%s: non-optional type may not follow optional type", kernelName); + validType = true; + if (optional) + optionalType = true; + if (!eitherOr) + size++; + break; + case '*': // accepts more of the same parameter (must be last char) + if (!validType) { + if ((writtenSig == curPos) || (*(curPos - 1) != ']')) + error("signature for k%s: a valid type must be in front of '*'", kernelName); } - } while (*src && (*src == KSIG_SPEC_ELLIPSIS || (c < 'a' && c != KSIG_SPEC_ANY))); - - // To handle sum types - result[index++] = v; + if (eitherOr) + error("signature for k%s: '*' may not be inside '[]'", kernelName); + if (optional) { + if ((*(curPos + 1) != ')') || (*(curPos + 2) != 0)) + error("signature for k%s: '*' may only be used for last type", kernelName); + } else { + if (*(curPos + 1) != 0) + error("signature for k%s: '*' may only be used for last type", kernelName); + } + break; + default: + error("signature for k%s: '%c' unknown", kernelName, *curPos); + } + curPos++; } - result[index] = 0; - *s = result; // Write back -} - -void Kernel::mapFunctions() { - int mapped = 0; - int ignored = 0; - uint functions_nr = _kernelNames.size(); - - _kernelFuncs.resize(functions_nr); - - for (uint functnr = 0; functnr < functions_nr; functnr++) { - int found = -1; - - // First, get the name, if known, of the kernel function with number functnr - Common::String sought_name = _kernelNames[functnr]; - - // Reset the table entry - _kernelFuncs[functnr].fun = NULL; - _kernelFuncs[functnr].signature = NULL; - _kernelFuncs[functnr].orig_name = sought_name; - - if (sought_name.empty()) { - // No name was given -> must be an unknown opcode - warning("Kernel function %x unknown", functnr); - _kernelFuncs[functnr].isDummy = true; - continue; + uint16 signature = 0; + + // Now we allocate buffer with required size and fill it + result = new uint16[size + 1]; + writePos = result; + curPos = writtenSig; + do { + curChar = *curPos; + if (!eitherOr) { + // not within either-or, check if next character forces output + switch (curChar) { + case 0: + case '[': + case '(': + case ')': + case 'i': + case 'o': + case 'r': + case 'l': + case 'n': + case '.': + case '!': + // and we also got some signature pending? + if (signature) { + if (!(signature & SIG_MAYBE_ANY)) + error("signature for k%s: invalid ('!') may only get used in combination with a real type", kernelName); + if ((signature & SIG_IS_INVALID) && ((signature & SIG_MAYBE_ANY) == (SIG_TYPE_NULL | SIG_TYPE_INTEGER))) + error("signature for k%s: invalid ('!') should not be used on exclusive null/integer type", kernelName); + if (optional) { + signature |= SIG_IS_OPTIONAL; + if (curChar != ')') + signature |= SIG_NEEDS_MORE; + } + *writePos = signature; + writePos++; + signature = 0; + } + } } - - // Don't map dummy functions - they will never be called - if (sought_name == "Dummy") { - _kernelFuncs[functnr].isDummy = true; - continue; + switch (curChar) { + case '[': // either or + eitherOr = true; + break; + case ']': // either or end + eitherOr = false; + break; + case '(': // optional + optional = true; + break; + case ')': // optional end + optional = false; + break; + case '0': + if (signature & SIG_TYPE_NULL) + error("signature for k%s: NULL ('0') specified more than once", kernelName); + signature |= SIG_TYPE_NULL; + break; + case 'i': + if (signature & SIG_TYPE_INTEGER) + error("signature for k%s: integer ('i') specified more than once", kernelName); + signature |= SIG_TYPE_INTEGER | SIG_TYPE_NULL; + break; + case 'o': + if (signature & SIG_TYPE_OBJECT) + error("signature for k%s: object ('o') specified more than once", kernelName); + signature |= SIG_TYPE_OBJECT; + break; + case 'r': + if (signature & SIG_TYPE_REFERENCE) + error("signature for k%s: reference ('r') specified more than once", kernelName); + signature |= SIG_TYPE_REFERENCE; + break; + case 'l': + if (signature & SIG_TYPE_LIST) + error("signature for k%s: list ('l') specified more than once", kernelName); + signature |= SIG_TYPE_LIST; + break; + case 'n': + if (signature & SIG_TYPE_NODE) + error("signature for k%s: node ('n') specified more than once", kernelName); + signature |= SIG_TYPE_NODE; + break; + case '.': + if (signature & SIG_MAYBE_ANY) + error("signature for k%s: maybe-any ('.') shouldn't get specified with other types in front of it", kernelName); + signature |= SIG_MAYBE_ANY; + break; + case '!': + if (signature & SIG_IS_INVALID) + error("signature for k%s: invalid ('!') specified more than once", kernelName); + signature |= SIG_IS_INVALID; + break; + case '*': // accepts more of the same parameter + signature |= SIG_MORE_MAY_FOLLOW; + break; + default: + break; } + curPos++; + } while (curChar); - // If the name is known, look it up in kfunct_mappers. This table - // maps kernel func names to actual function (pointers). - for (uint seeker = 0; (found == -1) && kfunct_mappers[seeker].name; seeker++) - if (sought_name == kfunct_mappers[seeker].name) - found = seeker; // Found a kernel function with the correct name! - - if (found == -1) { - // No match but a name was given -> stub - warning("Kernel function %s[%x] unmapped", sought_name.c_str(), functnr); - _kernelFuncs[functnr].isDummy = true; - } else { - // A match in kfunct_mappers was found - if (kfunct_mappers[found].fun) { - _kernelFuncs[functnr].fun = kfunct_mappers[found].fun; - _kernelFuncs[functnr].signature = kfunct_mappers[found].signature; - _kernelFuncs[functnr].isDummy = false; - kernel_compile_signature(&(_kernelFuncs[functnr].signature)); - ++mapped; - } else { - //warning("Ignoring function %s\n", kfunct_mappers[found].name); - ++ignored; - } - } - } // for all functions requesting to be mapped + // Write terminator + *writePos = 0; - debugC(2, kDebugLevelVM, "Handled %d/%d kernel functions, mapping %d and ignoring %d.", - mapped + ignored, _kernelNames.size(), mapped, ignored); - - return; + return result; } -int Kernel::findRegType(reg_t reg) { - // No segment? Must be arithmetic +uint16 Kernel::findRegType(reg_t reg) { + // No segment? Must be integer if (!reg.segment) - return reg.offset ? KSIG_ARITHMETIC : KSIG_ARITHMETIC | KSIG_NULL; + return SIG_TYPE_INTEGER | (reg.offset ? 0 : SIG_TYPE_NULL); + + if (reg.segment == 0xFFFF) + return SIG_TYPE_UNINITIALIZED; // Otherwise it's an object SegmentObj *mobj = _segMan->getSegmentObj(reg.segment); if (!mobj) - return 0; // Invalid + return SIG_TYPE_ERROR; + uint16 result = 0; if (!mobj->isValidOffset(reg.offset)) - warning("[KERN] ref %04x:%04x is invalid", PRINT_REG(reg)); + result |= SIG_IS_INVALID; switch (mobj->getType()) { case SEG_TYPE_SCRIPT: if (reg.offset <= (*(Script *)mobj).getBufSize() && reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && - RAW_IS_OBJECT((*(Script *)mobj)._buf + reg.offset)) { - return ((Script *)mobj)->getObject(reg.offset) ? KSIG_OBJECT : KSIG_REF; + RAW_IS_OBJECT((*(Script *)mobj).getBuf(reg.offset)) ) { + result |= ((Script *)mobj)->getObject(reg.offset) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE; } else - return KSIG_REF; + result |= SIG_TYPE_REFERENCE; + break; case SEG_TYPE_CLONES: - return KSIG_OBJECT; + result |= SIG_TYPE_OBJECT; + break; case SEG_TYPE_LOCALS: case SEG_TYPE_STACK: case SEG_TYPE_SYS_STRINGS: @@ -645,54 +968,286 @@ int Kernel::findRegType(reg_t reg) { case SEG_TYPE_ARRAY: case SEG_TYPE_STRING: #endif - return KSIG_REF; + result |= SIG_TYPE_REFERENCE; + break; case SEG_TYPE_LISTS: - return KSIG_LIST; + result |= SIG_TYPE_LIST; + break; case SEG_TYPE_NODES: - return KSIG_NODE; + result |= SIG_TYPE_NODE; + break; default: - return 0; + return SIG_TYPE_ERROR; } + return result; } -bool Kernel::signatureMatch(const char *sig, int argc, const reg_t *argv) { - // Always "match" if no signature is given - if (!sig) - return true; +struct SignatureDebugType { + uint16 typeCheck; + const char *text; +}; - while (*sig && argc) { - if ((*sig & KSIG_ANY) != KSIG_ANY) { - int type = findRegType(*argv); +static const SignatureDebugType signatureDebugTypeList[] = { + { SIG_TYPE_NULL, "null" }, + { SIG_TYPE_INTEGER, "integer" }, + { SIG_TYPE_UNINITIALIZED, "uninitialized" }, + { SIG_TYPE_OBJECT, "object" }, + { SIG_TYPE_REFERENCE, "reference" }, + { SIG_TYPE_LIST, "list" }, + { SIG_TYPE_NODE, "node" }, + { SIG_TYPE_ERROR, "error" }, + { SIG_IS_INVALID, "invalid" }, + { 0, NULL } +}; - if (!type) { - warning("[KERN] Could not determine type of ref %04x:%04x; failing signature check", PRINT_REG(*argv)); - return false; - } +static void kernelSignatureDebugType(const uint16 type) { + bool firstPrint = true; - if (!(type & *sig)) { - warning("kernel_matches_signature: %d args left, is %d, should be %d", argc, type, *sig); - return false; - } + const SignatureDebugType *list = signatureDebugTypeList; + while (list->typeCheck) { + if (type & list->typeCheck) { + if (!firstPrint) + printf(", "); + printf("%s", list->text); + firstPrint = false; + } + list++; + } +} +// Shows kernel call signature and current arguments for debugging purposes +void Kernel::signatureDebug(const uint16 *sig, int argc, const reg_t *argv) { + int argnr = 0; + while (*sig || argc) { + printf("parameter %d: ", argnr++); + if (argc) { + reg_t parameter = *argv; + printf("%04x:%04x (", PRINT_REG(parameter)); + int regType = findRegType(parameter); + if (regType) + kernelSignatureDebugType(regType); + else + printf("unknown type of %04x:%04x", PRINT_REG(parameter)); + printf(")"); + argv++; + argc--; + } else { + printf("not passed"); } - if (!(*sig & KSIG_ELLIPSIS)) - ++sig; - ++argv; - --argc; + if (*sig) { + const uint16 signature = *sig; + if ((signature & SIG_MAYBE_ANY) == SIG_MAYBE_ANY) { + printf(", may be any"); + } else { + printf(", should be "); + kernelSignatureDebugType(signature); + } + if (signature & SIG_IS_OPTIONAL) + printf(" (optional)"); + if (signature & SIG_NEEDS_MORE) + printf(" (needs more)"); + if (signature & SIG_MORE_MAY_FOLLOW) + printf(" (more may follow)"); + sig++; + } + printf("\n"); } +} + +bool Kernel::signatureMatch(const uint16 *sig, int argc, const reg_t *argv) { + uint16 nextSig = *sig; + uint16 curSig = nextSig; + while (nextSig && argc) { + curSig = nextSig; + int type = findRegType(*argv); + + if ((type & SIG_IS_INVALID) && (!(curSig & SIG_IS_INVALID))) + return false; // pointer is invalid and signature doesn't allow that? + + if (!((type & ~SIG_IS_INVALID) & curSig)) + return false; // type mismatch - if (argc) { - warning("kernel_matches_signature: too many arguments"); - return false; // Too many arguments + if (!(curSig & SIG_MORE_MAY_FOLLOW)) { + sig++; + nextSig = *sig; + } else { + nextSig |= SIG_IS_OPTIONAL; // more may follow -> assumes followers are optional + } + argv++; + argc--; } - if (*sig == 0 || (*sig & KSIG_ELLIPSIS)) + + // Too many arguments? + if (argc) + return false; + // Signature end reached? + if (nextSig == 0) return true; - warning("kernel_matches_signature: too few arguments"); + // current parameter is optional? + if (curSig & SIG_IS_OPTIONAL) { + // yes, check if nothing more is required + if (!(curSig & SIG_NEEDS_MORE)) + return true; + } else { + // no, check if next parameter is optional + if (nextSig & SIG_IS_OPTIONAL) + return true; + } + // Too few arguments or more optional arguments required return false; } -void Kernel::setDefaultKernelNames(Common::String gameId) { - _kernelNames = Common::StringArray(sci_default_knames, SCI_KNAMES_DEFAULT_ENTRIES_NR); +void Kernel::mapFunctions() { + int mapped = 0; + int ignored = 0; + uint functionCount = _kernelNames.size(); + byte platformMask = 0; + SciVersion myVersion = getSciVersion(); + + switch (g_sci->getPlatform()) { + case Common::kPlatformPC: + platformMask = SIGFOR_DOS; + break; + case Common::kPlatformPC98: + platformMask = SIGFOR_PC98; + break; + case Common::kPlatformWindows: + platformMask = SIGFOR_WIN; + break; + case Common::kPlatformMacintosh: + platformMask = SIGFOR_MAC; + break; + case Common::kPlatformAmiga: + platformMask = SIGFOR_AMIGA; + break; + case Common::kPlatformAtariST: + platformMask = SIGFOR_ATARI; + break; + default: + break; + } + + _kernelFuncs.resize(functionCount); + + for (uint id = 0; id < functionCount; id++) { + // First, get the name, if known, of the kernel function with number functnr + Common::String kernelName = _kernelNames[id]; + + // Reset the table entry + _kernelFuncs[id].function = NULL; + _kernelFuncs[id].signature = NULL; + _kernelFuncs[id].name = NULL; + _kernelFuncs[id].workarounds = NULL; + _kernelFuncs[id].subFunctions = NULL; + _kernelFuncs[id].subFunctionCount = 0; + _kernelFuncs[id].debugCalls = false; + if (kernelName.empty()) { + // No name was given -> must be an unknown opcode + warning("Kernel function %x unknown", id); + continue; + } + + // Don't map dummy functions - they will never be called + if (kernelName == "Dummy") { + _kernelFuncs[id].function = kDummy; + continue; + } + + // If the name is known, look it up in s_kernelMap. This table + // maps kernel func names to actual function (pointers). + SciKernelMapEntry *kernelMap = s_kernelMap; + bool nameMatch = false; + while (kernelMap->name) { + if (kernelName == kernelMap->name) { + if ((kernelMap->fromVersion == SCI_VERSION_NONE) || (kernelMap->fromVersion <= myVersion)) + if ((kernelMap->toVersion == SCI_VERSION_NONE) || (kernelMap->toVersion >= myVersion)) + if (platformMask & kernelMap->forPlatform) + break; + nameMatch = true; + } + kernelMap++; + } + + if (kernelMap->name) { + // A match was found + _kernelFuncs[id].function = kernelMap->function; + _kernelFuncs[id].name = kernelMap->name; + _kernelFuncs[id].signature = parseKernelSignature(kernelMap->name, kernelMap->signature); + _kernelFuncs[id].workarounds = kernelMap->workarounds; + if (kernelMap->subFunctions) { + // Get version for subfunction identification + SciVersion mySubVersion = (SciVersion)kernelMap->function(NULL, 0, NULL).offset; + // Now check whats the highest subfunction-id for this version + const SciKernelMapSubEntry *kernelSubMap = kernelMap->subFunctions; + uint16 subFunctionCount = 0; + while (kernelSubMap->function) { + if ((kernelSubMap->fromVersion == SCI_VERSION_NONE) || (kernelSubMap->fromVersion <= mySubVersion)) + if ((kernelSubMap->toVersion == SCI_VERSION_NONE) || (kernelSubMap->toVersion >= mySubVersion)) + if (subFunctionCount <= kernelSubMap->id) + subFunctionCount = kernelSubMap->id + 1; + kernelSubMap++; + } + if (!subFunctionCount) + error("k%s[%x]: no subfunctions found for requested version", kernelName.c_str(), id); + // Now allocate required memory and go through it again + _kernelFuncs[id].subFunctionCount = subFunctionCount; + KernelSubFunction *subFunctions = new KernelSubFunction[subFunctionCount]; + _kernelFuncs[id].subFunctions = subFunctions; + memset(subFunctions, 0, sizeof(KernelSubFunction) * subFunctionCount); + // And fill this info out + kernelSubMap = kernelMap->subFunctions; + uint kernelSubNr = 0; + while (kernelSubMap->function) { + if ((kernelSubMap->fromVersion == SCI_VERSION_NONE) || (kernelSubMap->fromVersion <= mySubVersion)) + if ((kernelSubMap->toVersion == SCI_VERSION_NONE) || (kernelSubMap->toVersion >= mySubVersion)) { + uint subId = kernelSubMap->id; + if (!subFunctions[subId].function) { + subFunctions[subId].function = kernelSubMap->function; + subFunctions[subId].name = kernelSubMap->name; + subFunctions[subId].workarounds = kernelSubMap->workarounds; + if (kernelSubMap->signature) { + subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMap->signature); + } else { + // we go back the submap to find the previous signature for that kernel call + const SciKernelMapSubEntry *kernelSubMapBack = kernelSubMap; + uint kernelSubLeft = kernelSubNr; + while (kernelSubLeft) { + kernelSubLeft--; + kernelSubMapBack--; + if (kernelSubMapBack->name == kernelSubMap->name) { + if (kernelSubMapBack->signature) { + subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMapBack->signature); + break; + } + } + } + if (!subFunctions[subId].signature) + error("k%s: no previous signatures", kernelSubMap->name); + } + } + } + kernelSubMap++; + kernelSubNr++; + } + } + ++mapped; + } else { + if (nameMatch) + error("k%s[%x]: not found for this version/platform", kernelName.c_str(), id); + // No match but a name was given -> stub + warning("k%s[%x]: unmapped", kernelName.c_str(), id); + _kernelFuncs[id].function = kStub; + } + } // for all functions requesting to be mapped + + debugC(2, kDebugLevelVM, "Handled %d/%d kernel functions, mapping %d and ignoring %d.", + mapped + ignored, _kernelNames.size(), mapped, ignored); + + return; +} + +void Kernel::setDefaultKernelNames() { + _kernelNames = Common::StringArray(s_defaultKernelNames, ARRAYSIZE(s_defaultKernelNames)); // Some (later) SCI versions replaced CanBeHere by CantBeHere if (_selectorCache.cantBeHere != -1) @@ -727,14 +1282,19 @@ void Kernel::setDefaultKernelNames(Common::String gameId) { break; case SCI_VERSION_1_1: - // In KQ6 CD, the empty kSetSynonyms function has been replaced - // with kPortrait. In KQ6 Mac, kPlayBack has been replaced by - // kShowMovie. - if (gameId == "kq6") { - if (g_sci->getPlatform() == Common::kPlatformMacintosh) - _kernelNames[0x84] = "ShowMovie"; - else + // In SCI1.1, kSetSynonyms is an empty function + _kernelNames[0x26] = "Empty"; + + if (g_sci->getGameId() == GID_KQ6) { + // In the Windows version of KQ6 CD, the empty kSetSynonyms + // function has been replaced with kPortrait. In KQ6 Mac, + // kPlayBack has been replaced by kShowMovie. + if (g_sci->getPlatform() == Common::kPlatformWindows) _kernelNames[0x26] = "Portrait"; + else if (g_sci->getPlatform() == Common::kPlatformMacintosh) + _kernelNames[0x84] = "ShowMovie"; + } else if (g_sci->getGameId() == GID_QFG4 && g_sci->isDemo()) { + _kernelNames[0x7b] = "RemapColors"; // QFG4 Demo has this SCI2 function instead of StrSplit } _kernelNames[0x71] = "PalVary"; @@ -747,20 +1307,19 @@ void Kernel::setDefaultKernelNames(Common::String gameId) { } } -bool Kernel::loadKernelNames(Common::String gameId) { +void Kernel::loadKernelNames(GameFeatures *features) { _kernelNames.clear(); #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2_1) - setKernelNamesSci21(); + setKernelNamesSci21(features); else if (getSciVersion() == SCI_VERSION_2) setKernelNamesSci2(); else #endif - setDefaultKernelNames(gameId); + setDefaultKernelNames(); mapFunctions(); - return true; } Common::String Kernel::lookupText(reg_t address, int index) { @@ -769,31 +1328,28 @@ Common::String Kernel::lookupText(reg_t address, int index) { if (address.segment) return _segMan->getString(address); - else { - int textlen; - int _index = index; - textres = _resMan->findResource(ResourceId(kResourceTypeText, address.offset), 0); - - if (!textres) { - error("text.%03d not found", address.offset); - return NULL; /* Will probably segfault */ - } - textlen = textres->size; - seeker = (char *) textres->data; + int textlen; + int _index = index; + textres = _resMan->findResource(ResourceId(kResourceTypeText, address.offset), 0); - while (index--) - while ((textlen--) && (*seeker++)) - ; + if (!textres) { + error("text.%03d not found", address.offset); + return NULL; /* Will probably segfault */ + } - if (textlen) - return seeker; - else { - error("Index %d out of bounds in text.%03d", _index, address.offset); - return NULL; - } + textlen = textres->size; + seeker = (char *) textres->data; - } + while (index--) + while ((textlen--) && (*seeker++)) + ; + + if (textlen) + return seeker; + + error("Index %d out of bounds in text.%03d", _index, address.offset); + return NULL; } } // End of namespace Sci diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 8f8f34f74e..fa206e8053 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -31,7 +31,7 @@ #include "common/rect.h" #include "common/str-array.h" -#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS +#include "sci/engine/selector.h" #include "sci/engine/vm_types.h" // for reg_t #include "sci/engine/vm.h" @@ -39,6 +39,7 @@ namespace Sci { struct Node; // from segment.h struct List; // from segment.h +struct SelectorCache; // from selector.h /** * @defgroup VocabularyResources Vocabulary resources in SCI @@ -92,59 +93,67 @@ struct List; // from segment.h //@{ //#define DEBUG_PARSER // enable for parser debugging -//#define DISABLE_VALIDATIONS // enable to stop validation checks // ---- Kernel signatures ----------------------------------------------------- -#define KSIG_TERMINATOR 0 - -// Uncompiled signatures -#define KSIG_SPEC_ARITMETIC 'i' -#define KSIG_SPEC_LIST 'l' -#define KSIG_SPEC_NODE 'n' -#define KSIG_SPEC_OBJECT 'o' -#define KSIG_SPEC_REF 'r' // Said Specs and strings -#define KSIG_SPEC_ARITHMETIC 'i' -#define KSIG_SPEC_NULL 'z' -#define KSIG_SPEC_ANY '.' -#define KSIG_SPEC_ELLIPSIS '*' // Arbitrarily more TYPED arguments - -#define KSIG_SPEC_SUM_DONE ('a' - 'A') // Use small letters to indicate end of sum type -/* Use capital letters for sum types, e.g. -** "LNoLr" for a function which takes two arguments: -** (1) list, node or object -** (2) list or ref -*/ - -// Compiled signatures -#define KSIG_LIST 0x01 -#define KSIG_NODE 0x02 -#define KSIG_OBJECT 0x04 -#define KSIG_REF 0x08 -#define KSIG_ARITHMETIC 0x10 - -#define KSIG_NULL 0x40 -#define KSIG_ANY 0x5f -#define KSIG_ELLIPSIS 0x80 + +// internal kernel signature data +enum { + SIG_TYPE_NULL = 0x01, // may be 0:0 [0] + SIG_TYPE_INTEGER = 0x02, // may be 0:* [i], automatically also allows null + SIG_TYPE_UNINITIALIZED = 0x04, // may be FFFF:* -> not allowable, only used for comparsion + SIG_TYPE_OBJECT = 0x08, // may be object [o] + SIG_TYPE_REFERENCE = 0x10, // may be reference [r] + SIG_TYPE_LIST = 0x20, // may be list [l] + SIG_TYPE_NODE = 0x40, // may be node [n] + SIG_TYPE_ERROR = 0x80, // happens, when there is a identification error - only used for comparsion + SIG_IS_INVALID = 0x100, // ptr is invalid [!] -> invalid offset + SIG_IS_OPTIONAL = 0x200, // is optional + SIG_NEEDS_MORE = 0x400, // needs at least one additional parameter following + SIG_MORE_MAY_FOLLOW = 0x800 // may have more parameters of the same type following +}; + +// this does not include SIG_TYPE_UNINITIALIZED, because we can not allow uninitialized values anywhere +#define SIG_MAYBE_ANY (SIG_TYPE_NULL | SIG_TYPE_INTEGER | SIG_TYPE_OBJECT | SIG_TYPE_REFERENCE | SIG_TYPE_LIST | SIG_TYPE_NODE) + // ---------------------------------------------------------------------------- /* Generic description: */ -typedef reg_t KernelFunc(EngineState *s, int argc, reg_t *argv); +typedef reg_t KernelFunctionCall(EngineState *s, int argc, reg_t *argv); + +struct SciWorkaroundEntry { + SciGameId gameId; + int scriptNr; + int16 inheritanceLevel; + const char *objectName; + const char *methodName; + int localCallOffset; + int index; + reg_t newValue; +}; + +#define SCI_WORKAROUNDENTRY_TERMINATOR { (SciGameId)0, -1, 0, NULL, NULL, -1, 0, { 0, 0 } } -struct KernelFuncWithSignature { - KernelFunc *fun; /**< The actual function */ - const char *signature; /**< KernelFunc signature */ - Common::String orig_name; /**< Original name, in case we couldn't map it */ - bool isDummy; +struct KernelSubFunction { + KernelFunctionCall *function; + const char *name; + uint16 *signature; + const SciWorkaroundEntry *workarounds; }; -enum AutoDetectedFeatures { - kFeatureOldScriptHeader = 1 << 0 +struct KernelFunction { + KernelFunctionCall *function; + const char *name; + uint16 *signature; + const SciWorkaroundEntry *workarounds; + const KernelSubFunction *subFunctions; + uint16 subFunctionCount; + bool debugCalls; }; class Kernel { public: /** - * Initializes the SCI kernel + * Initializes the SCI kernel. */ Kernel(ResourceManager *resMan, SegManager *segMan); ~Kernel(); @@ -156,18 +165,7 @@ public: const Common::String &getKernelName(uint number) const; /** - * Loads the kernel function names. - * - * This function reads the kernel function name table from resource_map, - * and fills the _kernelNames array with them. - * The resulting list has the same format regardless of the format of the - * name table of the resource (the format changed between version 0 and 1). - * @return true on success, false on failure - */ - bool loadKernelNames(Common::String gameId); - - /** - * Determines the selector ID of a selector by its name + * Determines the selector ID of a selector by its name. * @param selectorName Name of the selector to look up * @return The appropriate selector ID, or -1 on error */ @@ -178,22 +176,24 @@ public: void dumpScriptObject(char *data, int seeker, int objsize); void dumpScriptClass(char *data, int seeker, int objsize); - SelectorCache _selectorCache; /**< Shortcut list for important selectors */ - typedef Common::Array<KernelFuncWithSignature> KernelFuncsContainer; - KernelFuncsContainer _kernelFuncs; /**< Table of kernel functions */ + SelectorCache _selectorCache; /**< Shortcut list for important selectors. */ + typedef Common::Array<KernelFunction> KernelFunctionArray; + KernelFunctionArray _kernelFuncs; /**< Table of kernel functions. */ /** * Determines whether a list of registers matches a given signature. * If no signature is given (i.e., if sig is NULL), this is always * treated as a match. * - * @param segMan pointer to the segment manager * @param sig signature to test against * @param argc number of arguments to test * @param argv argument list * @return true if the signature was matched, false otherwise */ - bool signatureMatch(const char *sig, int argc, const reg_t *argv); + bool signatureMatch(const uint16 *sig, int argc, const reg_t *argv); + + // Prints out debug information in case a signature check fails + void signatureDebug(const uint16 *sig, int argc, const reg_t *argv); /** * Determines the type of the object indicated by reg. @@ -202,15 +202,15 @@ public: * KSIG_INVALID set if the type of reg can be determined, but is invalid. * 0 on error. */ - int findRegType(reg_t reg); + uint16 findRegType(reg_t reg); /******************** Text functionality ********************/ /** - * Looks up text referenced by scripts - * SCI uses two values to reference to text: An address, and an index. The address - * determines whether the text should be read from a resource file, or from the heap, - * while the index either refers to the number of the string in the specified source, - * or to a relative position inside the text. + * Looks up text referenced by scripts. + * SCI uses two values to reference to text: An address, and an index. The + * address determines whether the text should be read from a resource file, + * or from the heap, while the index either refers to the number of the + * string in the specified source, or to a relative position inside the text. * * @param address The address to look up * @param index The relative index @@ -218,22 +218,32 @@ public: */ Common::String lookupText(reg_t address, int index); + /** + * Loads the kernel function names. + * + * This function reads the kernel function name table from resource_map, + * and fills the _kernelNames array with them. + * The resulting list has the same format regardless of the format of the + * name table of the resource (the format changed between version 0 and 1). + */ + void loadKernelNames(GameFeatures *features); + private: /** - * Sets the default kernel function names, based on the SCI version used + * Sets the default kernel function names, based on the SCI version used. */ - void setDefaultKernelNames(Common::String gameId); + void setDefaultKernelNames(); #ifdef ENABLE_SCI32 /** - * Sets the default kernel function names to the SCI2 kernel functions + * Sets the default kernel function names to the SCI2 kernel functions. */ void setKernelNamesSci2(); /** - * Sets the default kernel function names to the SCI2.1 kernel functions + * Sets the default kernel function names to the SCI2.1 kernel functions. */ - void setKernelNamesSci21(); + void setKernelNamesSci21(GameFeatures *features); #endif /** @@ -248,36 +258,26 @@ private: Common::StringArray checkStaticSelectorNames(); /** - * Maps special selectors + * Maps special selectors. */ void mapSelectors(); /** - * Maps kernel functions + * Maps kernel functions. */ void mapFunctions(); ResourceManager *_resMan; SegManager *_segMan; - uint32 features; // Kernel-related lists Common::StringArray _selectorNames; Common::StringArray _kernelNames; + + const Common::String _invalid; }; -#ifdef USE_OLD_MUSIC_FUNCTIONS -/******************** Misc functions ********************/ - -/** - * Get all sound events, apply their changes to the heap - */ -void process_sound_events(EngineState *s); - -/******************** Constants ********************/ -#endif - -/* Maximum length of a savegame name (including terminator character) */ +/* Maximum length of a savegame name (including terminator character). */ #define SCI_MAX_SAVENAME_LENGTH 0x24 /******************** Kernel functions ********************/ @@ -423,6 +423,7 @@ reg_t kStrSplit(EngineState *s, int argc, reg_t *argv); reg_t kPlatform(EngineState *s, int argc, reg_t *argv); reg_t kTextColors(EngineState *s, int argc, reg_t *argv); reg_t kTextFonts(EngineState *s, int argc, reg_t *argv); +reg_t kEmpty(EngineState *s, int argc, reg_t *argv); #ifdef ENABLE_SCI32 // SCI2 Kernel Functions @@ -430,6 +431,7 @@ reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv); reg_t kArray(EngineState *s, int argc, reg_t *argv); reg_t kListAt(EngineState *s, int argc, reg_t *argv); reg_t kString(EngineState *s, int argc, reg_t *argv); +reg_t kMulDiv(EngineState *s, int argc, reg_t *argv); // "Screen items" in SCI32 are views reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv); reg_t kUpdateScreenItem(EngineState *s, int argc, reg_t *argv); @@ -451,12 +453,69 @@ reg_t kOnMe(EngineState *s, int argc, reg_t *argv); reg_t kInPolygon(EngineState *s, int argc, reg_t *argv); // SCI2.1 Kernel Functions +reg_t kText(EngineState *s, int argc, reg_t *argv); reg_t kSave(EngineState *s, int argc, reg_t *argv); reg_t kList(EngineState *s, int argc, reg_t *argv); reg_t kRobot(EngineState *s, int argc, reg_t *argv); +reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv); +reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv); +reg_t kCD(EngineState *s, int argc, reg_t *argv); #endif +reg_t kDoSoundInit(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundPlay(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundDummy(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundDispose(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundMute(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundStop(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundStopAll(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundPause(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundResume(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundMasterVolume(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundUpdate(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundFade(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundGetPolyphony(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundUpdateCues(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundSendMidi(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundReverb(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundSetHold(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundGetAudioCapability(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundSuspend(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundSetVolume(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundSetPriority(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundSetLoop(EngineState *s, int argc, reg_t *argv); + +reg_t kGraphGetColorCount(EngineState *s, int argc, reg_t *argv); +reg_t kGraphDrawLine(EngineState *s, int argc, reg_t *argv); +reg_t kGraphSaveBox(EngineState *s, int argc, reg_t *argv); +reg_t kGraphRestoreBox(EngineState *s, int argc, reg_t *argv); +reg_t kGraphFillBoxBackground(EngineState *s, int argc, reg_t *argv); +reg_t kGraphFillBoxForeground(EngineState *s, int argc, reg_t *argv); +reg_t kGraphFillBoxAny(EngineState *s, int argc, reg_t *argv); +reg_t kGraphUpdateBox(EngineState *s, int argc, reg_t *argv); +reg_t kGraphRedrawBox(EngineState *s, int argc, reg_t *argv); +reg_t kGraphAdjustPriority(EngineState *s, int argc, reg_t *argv); +reg_t kGraphSaveUpscaledHiresBox(EngineState *s, int argc, reg_t *argv); + +reg_t kPalVaryInit(EngineState *s, int argc, reg_t *argv); +reg_t kPalVaryReverse(EngineState *s, int argc, reg_t *argv); +reg_t kPalVaryGetCurrentStep(EngineState *s, int argc, reg_t *argv); +reg_t kPalVaryDeinit(EngineState *s, int argc, reg_t *argv); +reg_t kPalVaryChangeTarget(EngineState *s, int argc, reg_t *argv); +reg_t kPalVaryChangeTicks(EngineState *s, int argc, reg_t *argv); +reg_t kPalVaryPauseResume(EngineState *s, int argc, reg_t *argv); +reg_t kPalVaryUnknown(EngineState *s, int argc, reg_t *argv); + +reg_t kPaletteSetFromResource(EngineState *s, int argc, reg_t *argv); +reg_t kPaletteSetFlag(EngineState *s, int argc, reg_t *argv); +reg_t kPaletteUnsetFlag(EngineState *s, int argc, reg_t *argv); +reg_t kPaletteSetIntensity(EngineState *s, int argc, reg_t *argv); +reg_t kPaletteFindColor(EngineState *s, int argc, reg_t *argv); +reg_t kPaletteAnimate(EngineState *s, int argc, reg_t *argv); +reg_t kPaletteSave(EngineState *s, int argc, reg_t *argv); +reg_t kPaletteRestore(EngineState *s, int argc, reg_t *argv); + //@} } // End of namespace Sci diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index 0afdc3f2eb..eab1b90139 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -30,9 +30,8 @@ #include "sci/engine/segment.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" -#include "sci/graphics/gui.h" -#include "sci/graphics/gui32.h" #include "sci/graphics/frameout.h" +#include "sci/graphics/screen.h" #include "common/system.h" @@ -337,7 +336,7 @@ static const char *sci21_default_knames[] = { /*0x80*/ "Dummy", /*0x81*/ "Dummy", /*0x82*/ "Dummy", - /*0x83*/ "Dummy", + /*0x83*/ "PrintDebug", // used by the Shivers 2 demo /*0x84*/ "Dummy", /*0x85*/ "Dummy", /*0x86*/ "Dummy", @@ -378,15 +377,17 @@ void Kernel::setKernelNamesSci2() { _kernelNames = Common::StringArray(sci2_default_knames, kKernelEntriesSci2); } -void Kernel::setKernelNamesSci21() { - // Some SCI games use a modified SCI2 kernel table instead of the SCI2.1/SCI3 kernel table. - // The GK2 demo does this as well as at least one version of KQ7. We detect which version - // to use based on where kDoSound is called from Sound::play(). +void Kernel::setKernelNamesSci21(GameFeatures *features) { + // Some SCI games use a modified SCI2 kernel table instead of the + // SCI2.1/SCI3 kernel table. The GK2 demo does this as well as at + // least one version of KQ7. We detect which version to use based on + // where kDoSound is called from Sound::play(). - // This is interesting because they all have the same interpreter version (2.100.002), yet - // they would not be compatible with other games of the same interpreter. + // This is interesting because they all have the same interpreter + // version (2.100.002), yet they would not be compatible with other + // games of the same interpreter. - if (g_sci->_features->detectSci21KernelType() == SCI_VERSION_2) { + if (features->detectSci21KernelType() == SCI_VERSION_2) { _kernelNames = Common::StringArray(sci2_default_knames, kKernelEntriesGk2Demo); // OnMe is IsOnMe here, but they should be compatible _kernelNames[0x23] = "Robot"; // Graph in SCI2 @@ -400,7 +401,8 @@ void Kernel::setKernelNamesSci21() { // SCI2 Kernel Functions reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv) { - // Returns 0 if the screen width or height is less than 640 or 400, respectively. + // Returns 0 if the screen width or height is less than 640 or 400, + // respectively. if (g_system->getWidth() < 640 || g_system->getHeight() < 400) return make_reg(0, 0); @@ -461,6 +463,13 @@ reg_t kArray(EngineState *s, int argc, reg_t *argv) { return argv[1]; } case 6: { // Cpy + if (s->_segMan->getSegmentObj(argv[1].segment)->getType() != SEG_TYPE_ARRAY || + s->_segMan->getSegmentObj(argv[3].segment)->getType() != SEG_TYPE_ARRAY) { + // Happens in the RAMA demo + warning("kArray(Cpy): Request to copy a segment which isn't an array, ignoring"); + return NULL_REG; + } + SciArray<reg_t> *array1 = s->_segMan->lookupArray(argv[1]); SciArray<reg_t> *array2 = s->_segMan->lookupArray(argv[3]); uint32 index1 = argv[2].toUint16(); @@ -509,6 +518,19 @@ reg_t kArray(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } +reg_t kText(EngineState *s, int argc, reg_t *argv) { + switch (argv[0].toUint16()) { + case 0: + return kTextSize(s, argc - 1, argv + 1); + default: + // TODO: Other subops here too, perhaps kTextColors and kTextFonts + warning("kText(%d)", argv[0].toUint16()); + break; + } + + return s->r_acc; +} + reg_t kString(EngineState *s, int argc, reg_t *argv) { switch (argv[0].toUint16()) { case 0: { // New @@ -594,21 +616,24 @@ reg_t kString(EngineState *s, int argc, reg_t *argv) { if (argv[1].segment == s->_segMan->getSysStringsSegment()) { // Resize if necessary const uint16 sysStringId = argv[1].toUint16(); - if ((uint32)s->_segMan->sysStrings->_strings[sysStringId]._maxSize < index1 + count) { - free(s->_segMan->sysStrings->_strings[sysStringId]._value); - s->_segMan->sysStrings->_strings[sysStringId]._maxSize = index1 + count; - s->_segMan->sysStrings->_strings[sysStringId]._value = (char *)calloc(index1 + count, sizeof(char)); + SystemString *sysString = s->_segMan->getSystemString(sysStringId); + assert(sysString); + if ((uint32)sysString->_maxSize < index1 + count) { + free(sysString->_value); + sysString->_maxSize = index1 + count; + sysString->_value = (char *)calloc(index1 + count, sizeof(char)); } - strncpy(s->_segMan->sysStrings->_strings[sysStringId]._value + index1, string2 + index2, count); + strncpy(sysString->_value + index1, string2 + index2, count); } else { SciString *string1 = s->_segMan->lookupString(argv[1]); if (string1->getSize() < index1 + count) string1->setSize(index1 + count); - // Note: We're accessing from c_str() here because the string's size ignores - // the trailing 0 and therefore triggers an assert when doing string2[i + index2]. + // Note: We're accessing from c_str() here because the + // string's size ignores the trailing 0 and therefore + // triggers an assert when doing string2[i + index2]. for (uint16 i = 0; i < count; i++) string1->setValue(i + index1, string2[i + index2]); } @@ -791,8 +816,76 @@ reg_t kOnMe(EngineState *s, int argc, reg_t *argv) { nsRect.top = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsTop)); nsRect.right = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsRight)); nsRect.bottom = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsBottom)); + uint16 itemX = readSelectorValue(s->_segMan, targetObject, SELECTOR(x)); + uint16 itemY = readSelectorValue(s->_segMan, targetObject, SELECTOR(y)); + + // If top and left are negative, we need to adjust coordinates by + // the item's x and y (e.g. happens in GK1, day 1, with detective + // Mosely's hotspot in his office) - //warning("kOnMe: (%d, %d) on object %04x:%04x, parameter %d", argv[0].toUint16(), argv[1].toUint16(), PRINT_REG(argv[2]), argv[3].toUint16()); + if (nsRect.left < 0) + nsRect.translate(itemX, 0); + + if (nsRect.top < 0) + nsRect.translate(0, itemY); + + // HACK: nsLeft and nsTop can be invalid, so try and fix them here + // using x and y (e.g. with the inventory screen in GK1) + if (nsRect.left == itemY && nsRect.top == itemX) { + // Swap the values, as they're inversed (eh???) + nsRect.left = itemX; + nsRect.top = itemY; + } + + /* + warning("kOnMe: (%d, %d) on object %04x:%04x (%s), rect (%d, %d, %d, %d), parameter %d", + argv[0].toUint16(), argv[1].toUint16(), PRINT_REG(argv[2]), s->_segMan->getObjectName(argv[2]), + nsRect.left, nsRect.top, nsRect.right, nsRect.bottom, + argv[3].toUint16()); + */ + + return make_reg(0, nsRect.contains(x, y)); +} + +reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv) { + // Tests if the cursor is on the passed object, after adjusting the + // coordinates of the object according to the object's plane + + uint16 x = argv[0].toUint16(); + uint16 y = argv[1].toUint16(); + reg_t targetObject = argv[2]; + // TODO: argv[3] - it's usually 0 + Common::Rect nsRect; + + // Get the bounding rectangle of the object + nsRect.left = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsLeft)); + nsRect.top = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsTop)); + nsRect.right = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsRight)); + nsRect.bottom = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsBottom)); + + // Get the object's plane + reg_t planeObject = readSelector(s->_segMan, targetObject, SELECTOR(plane)); + if (!planeObject.isNull()) { + uint16 itemX = readSelectorValue(s->_segMan, targetObject, SELECTOR(x)); + uint16 itemY = readSelectorValue(s->_segMan, targetObject, SELECTOR(y)); + uint16 planeResY = readSelectorValue(s->_segMan, planeObject, SELECTOR(resY)); + uint16 planeResX = readSelectorValue(s->_segMan, planeObject, SELECTOR(resX)); + uint16 planeTop = readSelectorValue(s->_segMan, planeObject, SELECTOR(top)); + uint16 planeLeft = readSelectorValue(s->_segMan, planeObject, SELECTOR(left)); + planeTop = (planeTop * g_sci->_gfxScreen->getHeight()) / planeResY; + planeLeft = (planeLeft * g_sci->_gfxScreen->getWidth()) / planeResX; + + // Adjust the bounding rectangle of the object by the object's + // actual X, Y coordinates + itemY = ((itemY * g_sci->_gfxScreen->getHeight()) / planeResY); + itemX = ((itemX * g_sci->_gfxScreen->getWidth()) / planeResX); + itemY += planeTop; + itemX += planeLeft; + + nsRect.translate(itemX, itemY); + } + + //warning("kIsOnMe: (%d, %d) on object %04x:%04x, parameter %d", argv[0].toUint16(), argv[1].toUint16(), PRINT_REG(argv[2]), argv[3].toUint16()); return make_reg(0, nsRect.contains(x, y)); } @@ -805,7 +898,7 @@ reg_t kInPolygon(EngineState *s, int argc, reg_t *argv) { reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) { // TODO: argument 0 is usually 0, and arguments 1 and 2 are usually 1 switch (argv[0].toUint16()) { - case 0: + case 0: { if (argc != 4) { warning("kCreateTextBitmap(0): expected 4 arguments, got %i", argc); return NULL_REG; @@ -814,6 +907,22 @@ reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) { Common::String text = s->_segMan->getString(readSelector(s->_segMan, object, SELECTOR(text))); debug("kCreateTextBitmap: %s", text.c_str()); } + default: + warning("CreateTextBitmap(%d)", argv[0].toUint16()); + } + + return NULL_REG; +} + +reg_t kCD(EngineState *s, int argc, reg_t *argv) { + // TODO: Stub + switch (argv[0].toUint16()) { + case 0: + // Return whether the contents of disc argv[1] is available. + return TRUE_REG; + default: + warning("CD(%d)", argv[0].toUint16()); + } return NULL_REG; } diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index fd7711f196..7547ad5ab6 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -31,8 +31,6 @@ #include "sci/console.h" #include "sci/debug.h" // for g_debug_simulated_key #include "sci/event.h" -#include "sci/graphics/gui.h" -#include "sci/graphics/gui32.h" #include "sci/graphics/coordadjuster.h" #include "sci/graphics/cursor.h" @@ -43,7 +41,7 @@ namespace Sci { reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { int mask = argv[0].toUint16(); reg_t obj = argv[1]; - sciEvent curEvent; + SciEvent curEvent; int oldx, oldy; int modifier_mask = getSciVersion() <= SCI_VERSION_01 ? SCI_KEYMOD_ALL : SCI_KEYMOD_NO_FOOLOCK; SegManager *segMan = s->_segMan; @@ -67,7 +65,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { oldx = mousePos.x; oldy = mousePos.y; - curEvent = s->_event->get(mask); + curEvent = g_sci->getEventManager()->getSciEvent(mask); if (g_sci->getVocabulary()) g_sci->getVocabulary()->parser_event = NULL_REG; // Invalidate parser event @@ -79,7 +77,9 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { switch (curEvent.type) { case SCI_EVENT_QUIT: - quit_vm(s); + s->abortScriptProcessing = kAbortQuitGame; // Terminate VM + g_sci->_debugState.seeking = kDebugSeekNothing; + g_sci->_debugState.runningStep = 0; break; case SCI_EVENT_KEYBOARD: @@ -124,12 +124,12 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { s->r_acc = NULL_REG; // Unknown or no event } - if ((s->r_acc.offset) && (g_debugState.stopOnEvent)) { - g_debugState.stopOnEvent = false; + if ((s->r_acc.offset) && (g_sci->_debugState.stopOnEvent)) { + g_sci->_debugState.stopOnEvent = false; - // A SCI event occured, and we have been asked to stop, so open the debug console + // A SCI event occurred, and we have been asked to stop, so open the debug console Console *con = g_sci->getSciDebugger(); - con->DebugPrintf("SCI event occured: "); + con->DebugPrintf("SCI event occurred: "); switch (curEvent.type) { case SCI_EVENT_QUIT: con->DebugPrintf("quit event\n"); @@ -149,16 +149,14 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { con->onFrame(); } -#ifndef USE_OLD_MUSIC_FUNCTIONS if (g_sci->_features->detectDoSoundType() <= SCI_VERSION_0_LATE) { // If we're running a SCI0 game, update the sound cues, to compensate // for the fact that SCI0 does not poll to update the sound cues itself, // like SCI01 and later do with cmdUpdateSoundCues. kGetEvent is called // quite often, so emulate the SCI01 behavior of cmdUpdateSoundCues with // this call - s->_soundCmd->updateSci0Cues(); + g_sci->_soundCmd->updateSci0Cues(); } -#endif return s->r_acc; } @@ -203,7 +201,10 @@ reg_t kMapKeyToDir(EngineState *s, int argc, reg_t *argv) { } if (mover >= 0) { - writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_JOYSTICK); + if (g_sci->getEventManager()->getUsesNewKeyboardDirectionType()) + writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_KEYBOARD | SCI_EVENT_DIRECTION); + else + writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_DIRECTION); writeSelectorValue(segMan, obj, SELECTOR(message), mover); return make_reg(0, 1); } else diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 3e0ecd1a28..807edc63a5 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -36,12 +36,9 @@ namespace Sci { -enum { - MAX_SAVEGAME_NR = 20 /**< Maximum number of savegames */ -}; - struct SavegameDesc { - int id; + uint id; + int virtualId; // straight numbered, according to id but w/o gaps int date; int time; int version; @@ -115,15 +112,17 @@ void file_open(EngineState *s, const char *filename, int mode) { if (mode == _K_FILE_MODE_OPEN_OR_FAIL) { // Try to open file, abort if not possible inFile = saveFileMan->openForLoading(wrappedName); - // If no matching savestate exists: fall back to reading from a regular file + // If no matching savestate exists: fall back to reading from a regular + // file if (!inFile) inFile = SearchMan.createReadStreamForMember(englishName); - // Special case for LSL3: It tries to create a new dummy file, LARRY3.DRV - // Apparently, if the file doesn't exist here, it should be created. The game - // scripts then go ahead and fill its contents with data. It seems to be a similar - // case as the dummy MEMORY.DRV file in LSL5, but LSL5 creates the file if it can't - // find it with a separate call to file_open() + // Special case for LSL3: It tries to create a new dummy file, + // LARRY3.DRV. Apparently, if the file doesn't exist here, it should be + // created. The game scripts then go ahead and fill its contents with + // data. It seems to be a similar case as the dummy MEMORY.DRV file in + // LSL5, but LSL5 creates the file if it can't find it with a separate + // call to file_open(). if (!inFile && englishName == "LARRY3.DRV") { outFile = saveFileMan->openForSaving(wrappedName); outFile->finalize(); @@ -133,27 +132,28 @@ void file_open(EngineState *s, const char *filename, int mode) { } if (!inFile) - warning("file_open(_K_FILE_MODE_OPEN_OR_FAIL) failed to open file '%s'", englishName.c_str()); + warning(" -> file_open(_K_FILE_MODE_OPEN_OR_FAIL): failed to open file '%s'", englishName.c_str()); } else if (mode == _K_FILE_MODE_CREATE) { // Create the file, destroying any content it might have had outFile = saveFileMan->openForSaving(wrappedName); if (!outFile) - warning("file_open(_K_FILE_MODE_CREATE) failed to create file '%s'", englishName.c_str()); + warning(" -> file_open(_K_FILE_MODE_CREATE): failed to create file '%s'", englishName.c_str()); } else if (mode == _K_FILE_MODE_OPEN_OR_CREATE) { // Try to open file, create it if it doesn't exist outFile = saveFileMan->openForSaving(wrappedName); if (!outFile) - warning("file_open(_K_FILE_MODE_CREATE) failed to create file '%s'", englishName.c_str()); - // QfG1 opens the character export file with _K_FILE_MODE_CREATE first, closes it immediately and opens it again - // with this here - // Perhaps other games use this for read access as well - // I guess changing this whole code into using virtual files and writing them after close would be more appropriate + warning(" -> file_open(_K_FILE_MODE_CREATE): failed to create file '%s'", englishName.c_str()); + // QfG1 opens the character export file with _K_FILE_MODE_CREATE first, + // closes it immediately and opens it again with this here. Perhaps + // other games use this for read access as well. I guess changing this + // whole code into using virtual files and writing them after close + // would be more appropriate. } else { error("file_open: unsupported mode %d (filename '%s')", mode, englishName.c_str()); } if (!inFile && !outFile) { // Failed - debug(3, "file_open() failed"); + debugC(2, kDebugLevelFile, " -> file_open() failed"); s->r_acc = SIGNAL_REG; return; } @@ -163,7 +163,8 @@ void file_open(EngineState *s, const char *filename, int mode) { while ((handle < s->_fileHandles.size()) && s->_fileHandles[handle].isOpen()) handle++; - if (handle == s->_fileHandles.size()) { // Hit size limit => Allocate more space + if (handle == s->_fileHandles.size()) { + // Hit size limit => Allocate more space s->_fileHandles.resize(s->_fileHandles.size() + 1); } @@ -173,14 +174,14 @@ void file_open(EngineState *s, const char *filename, int mode) { s->r_acc = make_reg(0, handle); - debug(3, " -> opened file '%s' with handle %d", englishName.c_str(), handle); + debugC(2, kDebugLevelFile, " -> opened file '%s' with handle %d", englishName.c_str(), handle); } reg_t kFOpen(EngineState *s, int argc, reg_t *argv) { Common::String name = s->_segMan->getString(argv[0]); int mode = argv[1].toUint16(); - debug(3, "kFOpen(%s,0x%x)", name.c_str(), mode); + debugC(2, kDebugLevelFile, "kFOpen(%s,0x%x)", name.c_str(), mode); file_open(s, name.c_str(), mode); return s->r_acc; } @@ -200,7 +201,7 @@ static FileHandle *getFileFromHandle(EngineState *s, uint handle) { } reg_t kFClose(EngineState *s, int argc, reg_t *argv) { - debug(3, "kFClose(%d)", argv[0].toUint16()); + debugC(2, kDebugLevelFile, "kFClose(%d)", argv[0].toUint16()); if (argv[0] != SIGNAL_REG) { FileHandle *f = getFileFromHandle(s, argv[0].toUint16()); if (f) @@ -221,8 +222,6 @@ reg_t kFPuts(EngineState *s, int argc, reg_t *argv) { } static void fgets_wrapper(EngineState *s, char *dest, int maxsize, int handle) { - debugC(2, kDebugLevelFile, "FGets'ing %d bytes from handle %d", maxsize, handle); - FileHandle *f = getFileFromHandle(s, handle); if (!f) return; @@ -244,66 +243,7 @@ static void fgets_wrapper(EngineState *s, char *dest, int maxsize, int handle) { *dest = f->_in->readByte(); } - debugC(2, kDebugLevelFile, "FGets'ed \"%s\"", dest); -} - -static bool _savegame_index_struct_compare(const SavegameDesc &l, const SavegameDesc &r) { - if (l.date != r.date) - return (l.date > r.date); - return (l.time > r.time); -} - -void listSavegames(Common::Array<SavegameDesc> &saves) { - Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); - - // Load all saves - Common::StringArray saveNames = saveFileMan->listSavefiles(g_sci->getSavegamePattern()); - - for (Common::StringArray::const_iterator iter = saveNames.begin(); iter != saveNames.end(); ++iter) { - Common::String filename = *iter; - Common::SeekableReadStream *in; - if ((in = saveFileMan->openForLoading(filename))) { - SavegameMetadata meta; - if (!get_savegame_metadata(in, &meta) || meta.savegame_name.empty()) { - // invalid - delete in; - continue; - } - delete in; - - SavegameDesc desc; - desc.id = strtol(filename.end() - 3, NULL, 10); - desc.date = meta.savegame_date; - // We need to fix date in here, because we save DDMMYYYY instead of YYYYMMDD, so sorting wouldnt work - desc.date = ((desc.date & 0xFFFF) << 16) | ((desc.date & 0xFF0000) >> 8) | ((desc.date & 0xFF000000) >> 24); - desc.time = meta.savegame_time; - desc.version = meta.savegame_version; - - if (meta.savegame_name.lastChar() == '\n') - meta.savegame_name.deleteLastChar(); - - Common::strlcpy(desc.name, meta.savegame_name.c_str(), SCI_MAX_SAVENAME_LENGTH); - - debug(3, "Savegame in file %s ok, id %d", filename.c_str(), desc.id); - - saves.push_back(desc); - } - } - - // Sort the list by creation date of the saves - Common::sort(saves.begin(), saves.end(), _savegame_index_struct_compare); -} - -bool Console::cmdListSaves(int argc, const char **argv) { - Common::Array<SavegameDesc> saves; - listSavegames(saves); - - for (uint i = 0; i < saves.size(); i++) { - Common::String filename = g_sci->getSavegameName(saves[i].id); - DebugPrintf("%s: '%s'\n", filename.c_str(), saves[i].name); - } - - return true; + debugC(2, kDebugLevelFile, " -> FGets'ed \"%s\"", dest); } reg_t kFGets(EngineState *s, int argc, reg_t *argv) { @@ -311,7 +251,7 @@ reg_t kFGets(EngineState *s, int argc, reg_t *argv) { char *buf = new char[maxsize]; int handle = argv[2].toUint16(); - debug(3, "kFGets(%d,%d)", handle, maxsize); + debugC(2, kDebugLevelFile, "kFGets(%d, %d)", handle, maxsize); fgets_wrapper(s, buf, maxsize, handle); s->_segMan->memcpy(argv[0], (const byte*)buf, maxsize); return argv[0]; @@ -326,11 +266,14 @@ reg_t kGetCWD(EngineState *s, int argc, reg_t *argv) { // TODO/FIXME: Is "/" a good value? Maybe "" or "." or "C:\" are better? s->_segMan->strcpy(argv[0], "/"); - debug(3, "kGetCWD() -> %s", "/"); + debugC(2, kDebugLevelFile, "kGetCWD() -> %s", "/"); return argv[0]; } +static void listSavegames(Common::Array<SavegameDesc> &saves); +static int findSavegame(Common::Array<SavegameDesc> &saves, uint saveId); + enum { K_DEVICE_INFO_GET_DEVICE = 0, K_DEVICE_INFO_GET_CURRENT_DEVICE = 1, @@ -389,21 +332,25 @@ reg_t kDeviceInfo(EngineState *s, int argc, reg_t *argv) { break; case K_DEVICE_INFO_GET_SAVEFILE_NAME: { Common::String game_prefix = s->_segMan->getString(argv[2]); - int savegame_id = argv[3].toUint16(); + uint virtualId = argv[3].toUint16(); s->_segMan->strcpy(argv[1], "__throwaway"); - debug(3, "K_DEVICE_INFO_GET_SAVEFILE_NAME(%s,%d) -> %s", game_prefix.c_str(), savegame_id, "__throwaway"); + debug(3, "K_DEVICE_INFO_GET_SAVEFILE_NAME(%s,%d) -> %s", game_prefix.c_str(), virtualId, "__throwaway"); + if ((virtualId < SAVEGAMEID_OFFICIALRANGE_START) || (virtualId > SAVEGAMEID_OFFICIALRANGE_END)) + error("kDeviceInfo(deleteSave): invalid savegame-id specified"); + uint savegameId = virtualId - SAVEGAMEID_OFFICIALRANGE_START; Common::Array<SavegameDesc> saves; listSavegames(saves); - int savedir_nr = saves[savegame_id].id; - Common::String filename = g_sci->getSavegameName(savedir_nr); - Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); - saveFileMan->removeSavefile(filename); + if (findSavegame(saves, savegameId) != -1) { + // Confirmed that this id still lives... + Common::String filename = g_sci->getSavegameName(savegameId); + Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); + saveFileMan->removeSavefile(filename); } break; + } default: - // TODO: Not all sub-commands are handled. E.g. KQ5CD calls sub-command 5 - warning("Unknown DeviceInfo() sub-command: %d", mode); + error("Unknown DeviceInfo() sub-command: %d", mode); break; } @@ -430,27 +377,108 @@ reg_t kCheckFreeSpace(EngineState *s, int argc, reg_t *argv) { Common::String path = s->_segMan->getString(argv[0]); debug(3, "kCheckFreeSpace(%s)", path.c_str()); - // We simply always pretend that there is enough space. - // The alternative would be to write a big test file, which is not nice - // on systems where doing so is very slow. + // We simply always pretend that there is enough space. The alternative + // would be to write a big test file, which is not nice on systems where + // doing so is very slow. return make_reg(0, 1); } +static bool _savegame_sort_byDate(const SavegameDesc &l, const SavegameDesc &r) { + if (l.date != r.date) + return (l.date > r.date); + return (l.time > r.time); +} + +// Create a sorted array containing all found savedgames +static void listSavegames(Common::Array<SavegameDesc> &saves) { + Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); + + // Load all saves + Common::StringArray saveNames = saveFileMan->listSavefiles(g_sci->getSavegamePattern()); + + for (Common::StringArray::const_iterator iter = saveNames.begin(); iter != saveNames.end(); ++iter) { + Common::String filename = *iter; + Common::SeekableReadStream *in; + if ((in = saveFileMan->openForLoading(filename))) { + SavegameMetadata meta; + if (!get_savegame_metadata(in, &meta) || meta.savegame_name.empty()) { + // invalid + delete in; + continue; + } + delete in; + + SavegameDesc desc; + desc.id = strtol(filename.end() - 3, NULL, 10); + desc.date = meta.savegame_date; + // We need to fix date in here, because we save DDMMYYYY instead of + // YYYYMMDD, so sorting wouldn't work + desc.date = ((desc.date & 0xFFFF) << 16) | ((desc.date & 0xFF0000) >> 8) | ((desc.date & 0xFF000000) >> 24); + desc.time = meta.savegame_time; + desc.version = meta.savegame_version; + + if (meta.savegame_name.lastChar() == '\n') + meta.savegame_name.deleteLastChar(); + + Common::strlcpy(desc.name, meta.savegame_name.c_str(), SCI_MAX_SAVENAME_LENGTH); + + debug(3, "Savegame in file %s ok, id %d", filename.c_str(), desc.id); + + saves.push_back(desc); + } + } + + // Sort the list by creation date of the saves + Common::sort(saves.begin(), saves.end(), _savegame_sort_byDate); +} + +// Find a savedgame according to virtualId and return the position within our array +static int findSavegame(Common::Array<SavegameDesc> &saves, uint savegameId) { + for (uint saveNr = 0; saveNr < saves.size(); saveNr++) { + if (saves[saveNr].id == savegameId) + return saveNr; + } + return -1; +} + +// The scripts get IDs ranging from 1000->1999, because the scripts require us to assign unique ids THAT EVEN STAY BETWEEN +// SAVES and the scripts also use "saves-count + 1" to create a new savedgame slot. +// SCI1.1 actually recycles ids, in that case we will currently get "0". +// This behaviour is required especially for LSL6. In this game, it's possible to quick save. The scripts will use +// the last-used id for that feature. If we don't assign sticky ids, the feature will overwrite different saves all the +// time. And sadly we can't just use the actual filename ids directly, because of the creation method for new slots. + +bool Console::cmdListSaves(int argc, const char **argv) { + Common::Array<SavegameDesc> saves; + listSavegames(saves); + + for (uint i = 0; i < saves.size(); i++) { + Common::String filename = g_sci->getSavegameName(saves[i].id); + DebugPrintf("%s: '%s'\n", filename.c_str(), saves[i].name); + } + + return true; +} + reg_t kCheckSaveGame(EngineState *s, int argc, reg_t *argv) { Common::String game_id = s->_segMan->getString(argv[0]); - uint16 savedir_nr = argv[1].toUint16(); + uint16 virtualId = argv[1].toUint16(); - debug(3, "kCheckSaveGame(%s, %d)", game_id.c_str(), savedir_nr); + debug(3, "kCheckSaveGame(%s, %d)", game_id.c_str(), virtualId); Common::Array<SavegameDesc> saves; listSavegames(saves); - // Check for savegame slot being out of range - if (savedir_nr >= saves.size()) + // Find saved-game + if ((virtualId < SAVEGAMEID_OFFICIALRANGE_START) || (virtualId > SAVEGAMEID_OFFICIALRANGE_END)) + error("kCheckSaveGame: called with invalid savegameId!"); + uint savegameId = virtualId - SAVEGAMEID_OFFICIALRANGE_START; + int savegameNr = findSavegame(saves, savegameId); + if (savegameNr == -1) return NULL_REG; // Check for compatible savegame version - int ver = saves[savedir_nr].version; + int ver = saves[savegameNr].version; if (ver < MINIMUM_SAVEGAME_VERSION || ver > CURRENT_SAVEGAME_VERSION) return NULL_REG; @@ -463,9 +491,12 @@ reg_t kGetSaveFiles(EngineState *s, int argc, reg_t *argv) { debug(3, "kGetSaveFiles(%s)", game_id.c_str()); + // Scripts ask for current save files, we can assume that if afterwards they ask us to create a new slot they really + // mean new slot instead of overwriting the old one + s->_lastSaveVirtualId = SAVEGAMEID_OFFICIALRANGE_START; + Common::Array<SavegameDesc> saves; listSavegames(saves); - uint totalSaves = MIN<uint>(saves.size(), MAX_SAVEGAME_NR); reg_t *slot = s->_segMan->derefRegPtr(argv[2], totalSaves); @@ -480,7 +511,7 @@ reg_t kGetSaveFiles(EngineState *s, int argc, reg_t *argv) { char *saveNamePtr = saveNames; for (uint i = 0; i < totalSaves; i++) { - *slot++ = make_reg(0, i); // Store slot + *slot++ = make_reg(0, saves[i].id + SAVEGAMEID_OFFICIALRANGE_START); // Store the virtual savegame-id ffs. see above strcpy(saveNamePtr, saves[i].name); saveNamePtr += SCI_MAX_SAVENAME_LENGTH; } @@ -495,46 +526,51 @@ reg_t kGetSaveFiles(EngineState *s, int argc, reg_t *argv) { reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { Common::String game_id = s->_segMan->getString(argv[0]); - int savedir_nr = argv[1].toUint16(); - int savedir_id; // Savegame ID, derived from savedir_nr and the savegame ID list + uint virtualId = argv[1].toUint16(); Common::String game_description = s->_segMan->getString(argv[2]); Common::String version; if (argc > 3) version = s->_segMan->getString(argv[3]); - debug(3, "kSaveGame(%s,%d,%s,%s)", game_id.c_str(), savedir_nr, game_description.c_str(), version.c_str()); + debug(3, "kSaveGame(%s,%d,%s,%s)", game_id.c_str(), virtualId, game_description.c_str(), version.c_str()); Common::Array<SavegameDesc> saves; listSavegames(saves); - if (savedir_nr >= 0 && (uint)savedir_nr < saves.size()) { - // Overwrite - savedir_id = saves[savedir_nr].id; - } else if (savedir_nr >= 0 && savedir_nr < MAX_SAVEGAME_NR) { - uint i = 0; - - savedir_id = 0; - - // First, look for holes - while (i < saves.size()) { - if (saves[i].id == savedir_id) { - ++savedir_id; - i = 0; - } else - ++i; - } - if (savedir_id >= MAX_SAVEGAME_NR) { - warning("Internal error: Free savegame ID is %d, shouldn't happen", savedir_id); + uint savegameId; + if ((virtualId >= SAVEGAMEID_OFFICIALRANGE_START) && (virtualId <= SAVEGAMEID_OFFICIALRANGE_END)) { + // savegameId is an actual Id, so search for it just to make sure + savegameId = virtualId - SAVEGAMEID_OFFICIALRANGE_START; + if (findSavegame(saves, savegameId) != -1) return NULL_REG; + } else if (virtualId < SAVEGAMEID_OFFICIALRANGE_START) { + // virtualId is low, we assume that scripts expect us to create new slot + if (virtualId == s->_lastSaveVirtualId) { + // if last virtual id is the same as this one, we assume that caller wants to overwrite last save + savegameId = s->_lastSaveNewId; + } else { + uint savegameNr; + // savegameId is in lower range, scripts expect us to create a new slot + for (savegameId = 0; savegameId < SAVEGAMEID_OFFICIALRANGE_START; savegameId++) { + for (savegameNr = 0; savegameNr < saves.size(); savegameNr++) { + if (savegameId == saves[savegameNr].id) + break; + } + if (savegameNr == saves.size()) + break; + } + if (savegameId == SAVEGAMEID_OFFICIALRANGE_START) + error("kSavegame: no more savegame slots available"); } - - // This loop terminates when savedir_id is not in [x | ex. n. saves [n].id = x] } else { - warning("Savegame ID %d is not allowed", savedir_nr); - return NULL_REG; + error("kSaveGame: invalid savegameId used"); } - Common::String filename = g_sci->getSavegameName(savedir_id); + // Save in case caller wants to overwrite last newly created save + s->_lastSaveVirtualId = virtualId; + s->_lastSaveNewId = savegameId; + + Common::String filename = g_sci->getSavegameName(savegameId); Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); Common::OutSaveFile *out; if (!(out = saveFileMan->openForSaving(filename))) { @@ -543,7 +579,7 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } - if (gamestate_save(s, out, game_description.c_str(), version.c_str())) { + if (!gamestate_save(s, out, game_description.c_str(), version.c_str())) { warning("Saving the game failed."); s->r_acc = NULL_REG; } else { @@ -563,35 +599,37 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { Common::String game_id = !argv[0].isNull() ? s->_segMan->getString(argv[0]) : ""; - int savedir_nr = argv[1].toUint16(); + uint savegameId = argv[1].toUint16(); - debug(3, "kRestoreGame(%s,%d)", game_id.c_str(), savedir_nr); + debug(3, "kRestoreGame(%s,%d)", game_id.c_str(), savegameId); - if (!argv[0].isNull()) { - Common::Array<SavegameDesc> saves; - listSavegames(saves); + if ((savegameId < 1000) || (savegameId > 1999)) { + warning("Savegame ID %d is not allowed", savegameId); + return TRUE_REG; + } + savegameId -= 1000; - savedir_nr = saves[savedir_nr].id; - } else { - // Loading from launcher, no change necessary + Common::Array<SavegameDesc> saves; + listSavegames(saves); + if (findSavegame(saves, savegameId) == -1) { + warning("Savegame ID %d not found", savegameId); + return TRUE_REG; } - if (savedir_nr > -1) { - Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); - Common::String filename = g_sci->getSavegameName(savedir_nr); - Common::SeekableReadStream *in; - if ((in = saveFileMan->openForLoading(filename))) { - // found a savegame file + Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); + Common::String filename = g_sci->getSavegameName(savegameId); + Common::SeekableReadStream *in; + if ((in = saveFileMan->openForLoading(filename))) { + // found a savegame file - gamestate_restore(s, in); - delete in; + gamestate_restore(s, in); + delete in; - return s->r_acc; - } + return s->r_acc; } - s->r_acc = make_reg(0, 1); - warning("Savegame #%d not found", savedir_nr); + s->r_acc = TRUE_REG; + warning("Savegame #%d not found", savegameId); return s->r_acc; } @@ -642,7 +680,8 @@ reg_t DirSeeker::firstFile(const Common::String &mask, reg_t buffer, SegManager Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); _savefiles = saveFileMan->listSavefiles(wrappedMask); - // Reset the list iterator and write the first match to the output buffer, if any. + // Reset the list iterator and write the first match to the output buffer, + // if any. _iter = _savefiles.begin(); return nextFile(segMan); } @@ -672,7 +711,8 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { case K_FILEIO_OPEN : { Common::String name = s->_segMan->getString(argv[1]); - // SCI32 can call K_FILEIO_OPEN with only two arguments. It seems to just be checking if it exists. + // SCI32 can call K_FILEIO_OPEN with only two arguments. It seems to + // just be checking if it exists. int mode = (argc < 3) ? (int)_K_FILE_MODE_OPEN_OR_FAIL : argv[2].toUint16(); // SQ4 floppy prepends /\ to the filenames @@ -681,10 +721,10 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { name.deleteChar(0); } - // SQ4 floppy attempts to update the savegame index file sq4sg.dir - // when deleting saved games. We don't use an index file for saving - // or loading, so just stop the game from modifying the file here - // in order to avoid having it saved in the ScummVM save directory + // SQ4 floppy attempts to update the savegame index file sq4sg.dir when + // deleting saved games. We don't use an index file for saving or + // loading, so just stop the game from modifying the file here in order + // to avoid having it saved in the ScummVM save directory. if (name == "sq4sg.dir") { debugC(2, kDebugLevelFile, "Not opening unused file sq4sg.dir"); return SIGNAL_REG; @@ -694,12 +734,12 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { warning("Attempted to open a file with an empty filename"); return SIGNAL_REG; } + debugC(2, kDebugLevelFile, "kFileIO(open): %s, 0x%x", name.c_str(), mode); file_open(s, name.c_str(), mode); - debug(3, "K_FILEIO_OPEN(%s,0x%x)", name.c_str(), mode); break; } case K_FILEIO_CLOSE : { - debug(3, "K_FILEIO_CLOSE(%d)", argv[1].toUint16()); + debugC(2, kDebugLevelFile, "kFileIO(close): %d", argv[1].toUint16()); FileHandle *f = getFileFromHandle(s, argv[1].toUint16()); if (f) @@ -710,8 +750,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { int handle = argv[1].toUint16(); int size = argv[3].toUint16(); char *buf = new char[size]; - debug(3, "K_FILEIO_READ_RAW(%d,%d)", handle, size); - + debugC(2, kDebugLevelFile, "kFileIO(readRaw): %d, %d", handle, size); FileHandle *f = getFileFromHandle(s, handle); if (f) { @@ -727,7 +766,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { int size = argv[3].toUint16(); char *buf = new char[size]; s->_segMan->memcpy((byte*)buf, argv[2], size); - debug(3, "K_FILEIO_WRITE_RAW(%d,%d)", handle, size); + debugC(2, kDebugLevelFile, "kFileIO(writeRaw): %d, %d", handle, size); FileHandle *f = getFileFromHandle(s, handle); if (f) @@ -745,11 +784,13 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { name.deleteChar(0); } - // Special case for SQ4 floppy: This game has hardcoded names for all of its - // savegames, and they are all named "sq4sg.xxx", where xxx is the slot. We just - // take the slot number here, and delete the appropriate save game + // Special case for SQ4 floppy: This game has hardcoded names for all of + // its savegames, and they are all named "sq4sg.xxx", where xxx is the + // slot. We just take the slot number here, and delete the appropriate + // save game. if (name.hasPrefix("sq4sg.")) { - // Special handling for SQ4... get the slot number and construct the save game name + // Special handling for SQ4... get the slot number and construct the + // save game name. int slotNum = atoi(name.c_str() + name.size() - 3); Common::Array<SavegameDesc> saves; listSavegames(saves); @@ -761,7 +802,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { saveFileMan->removeSavefile(wrappedName); } - debug(3, "K_FILEIO_UNLINK(%s)", name.c_str()); + debugC(2, kDebugLevelFile, "kFileIO(unlink): %s", name.c_str()); // TODO/FIXME: Should we return something (like, a bool indicating // whether deleting the save succeeded or failed)? @@ -771,7 +812,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { int size = argv[2].toUint16(); char *buf = new char[size]; int handle = argv[3].toUint16(); - debug(3, "K_FILEIO_READ_STRING(%d,%d)", handle, size); + debugC(2, kDebugLevelFile, "kFileIO(readString): %d, %d", handle, size); fgets_wrapper(s, buf, size, handle); s->_segMan->memcpy(argv[1], (const byte*)buf, size); @@ -782,7 +823,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { int handle = argv[1].toUint16(); int size = argv[3].toUint16(); Common::String str = s->_segMan->getString(argv[2]); - debug(3, "K_FILEIO_WRITE_STRING(%d,%d)", handle, size); + debugC(2, kDebugLevelFile, "kFileIO(writeString): %d, %d", handle, size); // CHECKME: Is the size parameter used at all? // In the LSL5 password protection it is zero, and we should @@ -798,7 +839,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { int handle = argv[1].toUint16(); int offset = argv[2].toUint16(); int whence = argv[3].toUint16(); - debug(3, "K_FILEIO_SEEK(%d,%d,%d)", handle, offset, whence); + debugC(2, kDebugLevelFile, "kFileIO(seek): %d, %d, %d", handle, offset, whence); FileHandle *f = getFileFromHandle(s, handle); if (f) @@ -809,7 +850,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { Common::String mask = s->_segMan->getString(argv[1]); reg_t buf = argv[2]; int attr = argv[3].toUint16(); // We won't use this, Win32 might, though... - debug(3, "K_FILEIO_FIND_FIRST(%s,0x%x)", mask.c_str(), attr); + debugC(2, kDebugLevelFile, "kFileIO(findFirst): %s, 0x%x", mask.c_str(), attr); // We remove ".*". mask will get prefixed, so we will return all additional files for that gameid if (mask == "*.*") @@ -827,7 +868,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { break; } case K_FILEIO_FIND_NEXT : { - debug(3, "K_FILEIO_FIND_NEXT()"); + debugC(2, kDebugLevelFile, "kFileIO(findNext)"); s->r_acc = s->_dirseeker.nextFile(s->_segMan); break; } @@ -849,14 +890,17 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { delete inFile; } - // Special case for non-English versions of LSL5: The English version of LSL5 calls - // kFileIO(), case K_FILEIO_OPEN for reading to check if memory.drv exists (which is - // where the game's password is stored). If it's not found, it calls kFileIO() again, - // case K_FILEIO_OPEN for writing and creates a new file. Non-English versions call - // kFileIO(), case K_FILEIO_FILE_EXISTS instead, and fail if memory.drv can't be found. - // We create a default memory.drv file with no password, so that the game can continue + // Special case for non-English versions of LSL5: The English version of + // LSL5 calls kFileIO(), case K_FILEIO_OPEN for reading to check if + // memory.drv exists (which is where the game's password is stored). If + // it's not found, it calls kFileIO() again, case K_FILEIO_OPEN for + // writing and creates a new file. Non-English versions call kFileIO(), + // case K_FILEIO_FILE_EXISTS instead, and fail if memory.drv can't be + // found. We create a default memory.drv file with no password, so that + // the game can continue. if (!exists && name == "memory.drv") { - // Create a new file, and write the bytes for the empty password string inside + // Create a new file, and write the bytes for the empty password + // string inside byte defaultContent[] = { 0xE9, 0xE9, 0xEB, 0xE1, 0x0D, 0x0A, 0x31, 0x30, 0x30, 0x30 }; Common::WriteStream *outFile = saveFileMan->openForSaving(wrappedName); for (int i = 0; i < 10; i++) @@ -866,15 +910,15 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { exists = true; } - debug(3, "K_FILEIO_FILE_EXISTS(%s) -> %d", name.c_str(), exists); + debugC(2, kDebugLevelFile, "kFileIO(fileExists) %s -> %d", name.c_str(), exists); return make_reg(0, exists); } case K_FILEIO_RENAME: { Common::String oldName = s->_segMan->getString(argv[1]); Common::String newName = s->_segMan->getString(argv[2]); - // SCI1.1 returns 0 on success and a DOS error code on fail. SCI32 returns -1 on fail. - // We just return -1 for all versions. + // SCI1.1 returns 0 on success and a DOS error code on fail. SCI32 + // returns -1 on fail. We just return -1 for all versions. if (g_engine->getSaveFileManager()->renameSavefile(oldName, newName)) return NULL_REG; else @@ -914,7 +958,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { break; #endif default: - error("Unknown FileIO() sub-command: %d", func_nr); + error("kFileIO(): unknown sub-command: %d", func_nr); } return s->r_acc; diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index abe55455de..29f7565ef9 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -37,8 +37,6 @@ #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/engine/kernel.h" -#include "sci/graphics/gui.h" -#include "sci/graphics/gui32.h" #include "sci/graphics/animate.h" #include "sci/graphics/cache.h" #include "sci/graphics/compare.h" @@ -48,7 +46,11 @@ #include "sci/graphics/paint16.h" #include "sci/graphics/ports.h" #include "sci/graphics/screen.h" +#include "sci/graphics/text16.h" #include "sci/graphics/view.h" +#ifdef ENABLE_SCI32 +#include "sci/video/vmd_decoder.h" +#endif namespace Sci { @@ -171,7 +173,7 @@ static reg_t kSetCursorSci11(EngineState *s, int argc, reg_t *argv) { g_sci->_gfxCursor->kernelSetView(argv[0].toUint16(), argv[1].toUint16(), argv[2].toUint16(), hotspot); break; default : - warning("kSetCursor: Unhandled case: %d arguments given", argc); + error("kSetCursor: Unhandled case: %d arguments given", argc); break; } return s->r_acc; @@ -184,7 +186,7 @@ reg_t kSetCursor(EngineState *s, int argc, reg_t *argv) { case SCI_VERSION_1_1: return kSetCursorSci11(s, argc, argv); default: - warning("Unknown SetCursor type"); + error("Unknown SetCursor type"); return NULL_REG; } } @@ -205,121 +207,108 @@ reg_t kPicNotValid(EngineState *s, int argc, reg_t *argv) { return make_reg(0, g_sci->_gfxScreen->kernelPicNotValid(newPicNotValid)); } -Common::Rect kGraphCreateRect(int16 x, int16 y, int16 x1, int16 y1) { +static Common::Rect getGraphRect(reg_t *argv) { + int16 x = argv[1].toSint16(); + int16 y = argv[0].toSint16(); + int16 x1 = argv[3].toSint16(); + int16 y1 = argv[2].toSint16(); if (x > x1) SWAP(x, x1); if (y > y1) SWAP(y, y1); return Common::Rect(x, y, x1, y1); } -// Graph subfunctions -enum { - K_GRAPH_GET_COLORS_NR = 2, - // 3 - SET PALETTE VIA RESOURCE - K_GRAPH_DRAW_LINE = 4, - // 5 - NOP - // 6 - DRAW PATTERN - K_GRAPH_SAVE_BOX = 7, - K_GRAPH_RESTORE_BOX = 8, - K_GRAPH_FILL_BOX_BACKGROUND = 9, - K_GRAPH_FILL_BOX_FOREGROUND = 10, - K_GRAPH_FILL_BOX_ANY = 11, - K_GRAPH_UPDATE_BOX = 12, - K_GRAPH_REDRAW_BOX = 13, - K_GRAPH_ADJUST_PRIORITY = 14, - K_GRAPH_SAVE_UPSCALEDHIRES_BOX = 15 // KQ6CD Windows version -}; +static Common::Point getGraphPoint(reg_t *argv) { + int16 x = argv[1].toSint16(); + int16 y = argv[0].toSint16(); + return Common::Point(x, y); +} reg_t kGraph(EngineState *s, int argc, reg_t *argv) { - int16 x = 0, y = 0, x1 = 0, y1 = 0; - uint16 screenMask; - int16 priority, control, color, colorMask; - Common::Rect rect; - - if (argc >= 5) { - x = argv[2].toSint16(); - y = argv[1].toSint16(); - x1 = argv[4].toSint16(); - y1 = argv[3].toSint16(); - } - - switch (argv[0].toSint16()) { - case K_GRAPH_GET_COLORS_NR: - if (g_sci->getResMan()->isAmiga32color()) - return make_reg(0, 32); - return make_reg(0, !g_sci->getResMan()->isVGA() ? 16 : 256); - - case K_GRAPH_DRAW_LINE: - priority = (argc > 6) ? argv[6].toSint16() : -1; - control = (argc > 7) ? argv[7].toSint16() : -1; - color = argv[5].toSint16(); - - // TODO: Find out why we get >15 for color in EGA - if (!g_sci->getResMan()->isVGA() && !g_sci->getResMan()->isAmiga32color()) - color &= 0x0F; + if (!s) + return make_reg(0, getSciVersion()); + error("not supposed to call this"); +} - g_sci->_gfxPaint16->kernelGraphDrawLine(Common::Point(x, y), Common::Point(x1, y1), color, priority, control); - break; +reg_t kGraphGetColorCount(EngineState *s, int argc, reg_t *argv) { + if (g_sci->getResMan()->isAmiga32color()) + return make_reg(0, 32); + return make_reg(0, !g_sci->getResMan()->isVGA() ? 16 : 256); +} - case K_GRAPH_SAVE_BOX: - rect = kGraphCreateRect(x, y, x1, y1); - screenMask = (argc > 5) ? argv[5].toUint16() : 0; - return g_sci->_gfxPaint16->kernelGraphSaveBox(rect, screenMask); +reg_t kGraphDrawLine(EngineState *s, int argc, reg_t *argv) { + int16 color = argv[4].toSint16(); + int16 priority = (argc > 5) ? argv[5].toSint16() : -1; + int16 control = (argc > 6) ? argv[6].toSint16() : -1; - case K_GRAPH_RESTORE_BOX: - // This may be called with a memoryhandle from SAVE_BOX or SAVE_UPSCALEDHIRES_BOX - g_sci->_gfxPaint16->kernelGraphRestoreBox(argv[1]); - break; + // TODO: Find out why we get >15 for color in EGA + if (!g_sci->getResMan()->isVGA() && !g_sci->getResMan()->isAmiga32color()) + color &= 0x0F; - case K_GRAPH_FILL_BOX_BACKGROUND: - rect = kGraphCreateRect(x, y, x1, y1); - g_sci->_gfxPaint16->kernelGraphFillBoxBackground(rect); - break; + g_sci->_gfxPaint16->kernelGraphDrawLine(getGraphPoint(argv), getGraphPoint(argv + 2), color, priority, control); + return s->r_acc; +} - case K_GRAPH_FILL_BOX_FOREGROUND: - rect = kGraphCreateRect(x, y, x1, y1); - g_sci->_gfxPaint16->kernelGraphFillBoxForeground(rect); - break; +reg_t kGraphSaveBox(EngineState *s, int argc, reg_t *argv) { + Common::Rect rect = getGraphRect(argv); + uint16 screenMask = (argc > 4) ? argv[4].toUint16() : 0; + return g_sci->_gfxPaint16->kernelGraphSaveBox(rect, screenMask); +} - case K_GRAPH_FILL_BOX_ANY: - priority = (argc > 7) ? argv[7].toSint16() : -1; - control = (argc > 8) ? argv[8].toSint16() : -1; - color = argv[6].toSint16(); - colorMask = argv[5].toUint16(); +reg_t kGraphRestoreBox(EngineState *s, int argc, reg_t *argv) { + // This may be called with a memoryhandle from SAVE_BOX or SAVE_UPSCALEDHIRES_BOX + g_sci->_gfxPaint16->kernelGraphRestoreBox(argv[0]); + return s->r_acc; +} - rect = kGraphCreateRect(x, y, x1, y1); - g_sci->_gfxPaint16->kernelGraphFillBox(rect, colorMask, color, priority, control); - break; +reg_t kGraphFillBoxBackground(EngineState *s, int argc, reg_t *argv) { + Common::Rect rect = getGraphRect(argv); + g_sci->_gfxPaint16->kernelGraphFillBoxBackground(rect); + return s->r_acc; +} - case K_GRAPH_UPDATE_BOX: { - rect = kGraphCreateRect(x, y, x1, y1); - bool hiresMode = (argc > 6) ? true : false; - // argc == 7 on upscaled hires - g_sci->_gfxPaint16->kernelGraphUpdateBox(rect, hiresMode); - break; - } +reg_t kGraphFillBoxForeground(EngineState *s, int argc, reg_t *argv) { + Common::Rect rect = getGraphRect(argv); + g_sci->_gfxPaint16->kernelGraphFillBoxForeground(rect); + return s->r_acc; +} - case K_GRAPH_REDRAW_BOX: - rect = kGraphCreateRect(x, y, x1, y1); - g_sci->_gfxPaint16->kernelGraphRedrawBox(rect); - break; +reg_t kGraphFillBoxAny(EngineState *s, int argc, reg_t *argv) { + Common::Rect rect = getGraphRect(argv); + int16 colorMask = argv[4].toUint16(); + int16 color = argv[5].toSint16(); + int16 priority = (argc > 6) ? argv[6].toSint16() : -1; + int16 control = (argc > 7) ? argv[7].toSint16() : -1; - case K_GRAPH_ADJUST_PRIORITY: - // Seems to be only implemented for SCI0/SCI01 games - debugC(2, kDebugLevelGraphics, "adjust_priority(%d, %d)", argv[1].toUint16(), argv[2].toUint16()); - g_sci->_gfxPorts->kernelGraphAdjustPriority(argv[1].toUint16(), argv[2].toUint16()); - break; + g_sci->_gfxPaint16->kernelGraphFillBox(rect, colorMask, color, priority, control); + return s->r_acc; +} - case K_GRAPH_SAVE_UPSCALEDHIRES_BOX: - rect = kGraphCreateRect(x, y, x1, y1); - return g_sci->_gfxPaint16->kernelGraphSaveUpscaledHiresBox(rect); +reg_t kGraphUpdateBox(EngineState *s, int argc, reg_t *argv) { + Common::Rect rect = getGraphRect(argv); + // argv[4] is the map (1 for visual, etc.) + // argc == 6 on upscaled hires + bool hiresMode = (argc > 5) ? true : false; + g_sci->_gfxPaint16->kernelGraphUpdateBox(rect, hiresMode); + return s->r_acc; +} - default: - warning("Unsupported kGraph() operation %04x", argv[0].toSint16()); - } +reg_t kGraphRedrawBox(EngineState *s, int argc, reg_t *argv) { + Common::Rect rect = getGraphRect(argv); + g_sci->_gfxPaint16->kernelGraphRedrawBox(rect); + return s->r_acc; +} +// Seems to be only implemented for SCI0/SCI01 games +reg_t kGraphAdjustPriority(EngineState *s, int argc, reg_t *argv) { + g_sci->_gfxPorts->kernelGraphAdjustPriority(argv[0].toUint16(), argv[1].toUint16()); return s->r_acc; } +reg_t kGraphSaveUpscaledHiresBox(EngineState *s, int argc, reg_t *argv) { + Common::Rect rect = getGraphRect(argv); + return g_sci->_gfxPaint16->kernelGraphSaveUpscaledHiresBox(rect); +} + reg_t kTextSize(EngineState *s, int argc, reg_t *argv) { int16 textWidth, textHeight; Common::String text = s->_segMan->getString(argv[1]); @@ -343,13 +332,14 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) { } textWidth = dest[3].toUint16(); textHeight = dest[2].toUint16(); - + #ifdef ENABLE_SCI32 - if (g_sci->_gui32) - g_sci->_gui32->textSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight); - else + if (!g_sci->_gfxText16) { + // TODO: Implement this + textWidth = 0; textHeight = 0; + } else #endif - g_sci->_gui->textSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight); + g_sci->_gfxText16->kernelTextSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight); debugC(2, kDebugLevelStrings, "GetTextSize '%s' -> %dx%d", text.c_str(), textWidth, textHeight); dest[2] = make_reg(0, textHeight); @@ -531,7 +521,7 @@ reg_t kBaseSetter(EngineState *s, int argc, reg_t *argv) { // WORKAROUND for a problem in LSL1VGA. This allows the casino door to be opened, // till the actual problem is found - if (!strcmp(g_sci->getGameID(), "lsl1sci") && s->currentRoomNumber() == 300) { + if (s->currentRoomNumber() == 300 && g_sci->getGameId() == GID_LSL1) { int top = readSelectorValue(s->_segMan, object, SELECTOR(brTop)); writeSelectorValue(s->_segMan, object, SELECTOR(brTop), top + 2); } @@ -545,64 +535,72 @@ reg_t kSetNowSeen(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } +// we are called on EGA/amiga games as well, this doesnt make sense. +// doing this would actually break the system EGA/amiga palette reg_t kPalette(EngineState *s, int argc, reg_t *argv) { - // we are called on EGA/amiga games as well, this doesnt make sense. - // doing this would actually break the system EGA/amiga palette - if (!g_sci->getResMan()->isVGA()) - return s->r_acc; + if (!s) + return make_reg(0, getSciVersion()); + error("not supposed to call this"); +} - switch (argv[0].toUint16()) { - case 1: // Set resource palette - if (argc==3) { - GuiResourceId resourceId = argv[1].toUint16(); - bool force = argv[2].toUint16() == 2 ? true : false; - g_sci->_gfxPalette->kernelSetFromResource(resourceId, force); - } else { - warning("kPalette(1) called with %d parameters", argc); - } - break; - case 2: { // Set palette-flag(s) - uint16 fromColor = CLIP<uint16>(argv[1].toUint16(), 1, 255); - uint16 toColor = CLIP<uint16>(argv[2].toUint16(), 1, 255); - uint16 flags = argv[3].toUint16(); +reg_t kPaletteSetFromResource(EngineState *s, int argc, reg_t *argv) { + if (g_sci->getResMan()->isVGA()) { + GuiResourceId resourceId = argv[0].toUint16(); + bool force = false; + if (argc == 2) + force = argv[1].toUint16() == 2 ? true : false; + g_sci->_gfxPalette->kernelSetFromResource(resourceId, force); + } + return s->r_acc; +} + +reg_t kPaletteSetFlag(EngineState *s, int argc, reg_t *argv) { + if (g_sci->getResMan()->isVGA()) { + uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255); + uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255); + uint16 flags = argv[2].toUint16(); g_sci->_gfxPalette->kernelSetFlag(fromColor, toColor, flags); - break; } - case 3: { // Remove palette-flag(s) - uint16 fromColor = CLIP<uint16>(argv[1].toUint16(), 1, 255); - uint16 toColor = CLIP<uint16>(argv[2].toUint16(), 1, 255); - uint16 flags = argv[3].toUint16(); + return s->r_acc; +} + +reg_t kPaletteUnsetFlag(EngineState *s, int argc, reg_t *argv) { + if (g_sci->getResMan()->isVGA()) { + uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255); + uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255); + uint16 flags = argv[2].toUint16(); g_sci->_gfxPalette->kernelUnsetFlag(fromColor, toColor, flags); - break; } - case 4: { // Set palette intensity - switch (argc) { - case 4: - case 5: { - uint16 fromColor = CLIP<uint16>(argv[1].toUint16(), 1, 255); - uint16 toColor = CLIP<uint16>(argv[2].toUint16(), 1, 255); - uint16 intensity = argv[3].toUint16(); - bool setPalette = (argc < 5) ? true : (argv[4].isNull()) ? true : false; - - g_sci->_gfxPalette->kernelSetIntensity(fromColor, toColor, intensity, setPalette); - break; - } - default: - warning("kPalette(4) called with %d parameters", argc); - } - break; + return s->r_acc; +} + +reg_t kPaletteSetIntensity(EngineState *s, int argc, reg_t *argv) { + if (g_sci->getResMan()->isVGA()) { + uint16 fromColor = CLIP<uint16>(argv[0].toUint16(), 1, 255); + uint16 toColor = CLIP<uint16>(argv[1].toUint16(), 1, 255); + uint16 intensity = argv[2].toUint16(); + bool setPalette = (argc < 4) ? true : (argv[3].isNull()) ? true : false; + + g_sci->_gfxPalette->kernelSetIntensity(fromColor, toColor, intensity, setPalette); } - case 5: { // Find closest color - uint16 r = argv[1].toUint16(); - uint16 g = argv[2].toUint16(); - uint16 b = argv[3].toUint16(); + return s->r_acc; +} +reg_t kPaletteFindColor(EngineState *s, int argc, reg_t *argv) { + if (g_sci->getResMan()->isVGA()) { + uint16 r = argv[0].toUint16(); + uint16 g = argv[1].toUint16(); + uint16 b = argv[2].toUint16(); return make_reg(0, g_sci->_gfxPalette->kernelFindColor(r, g, b)); } - case 6: { // Animate + return NULL_REG; +} + +reg_t kPaletteAnimate(EngineState *s, int argc, reg_t *argv) { + if (g_sci->getResMan()->isVGA()) { int16 argNr; bool paletteChanged = false; - for (argNr = 1; argNr < argc; argNr += 3) { + for (argNr = 0; argNr < argc; argNr += 3) { uint16 fromColor = argv[argNr].toUint16(); uint16 toColor = argv[argNr + 1].toUint16(); int16 speed = argv[argNr + 2].toSint16(); @@ -611,80 +609,82 @@ reg_t kPalette(EngineState *s, int argc, reg_t *argv) { } if (paletteChanged) g_sci->_gfxPalette->kernelAnimateSet(); - break; } - case 7: { // Save palette to heap + return s->r_acc; +} + +reg_t kPaletteSave(EngineState *s, int argc, reg_t *argv) { + if (g_sci->getResMan()->isVGA()) { warning("kPalette(7), save palette to heap STUB"); - break; - } - case 8: { // Restore palette from heap - warning("kPalette(8), set stored palette STUB"); - break; - } - default: - warning("kPalette(%d), not implemented", argv[0].toUint16()); } + return NULL_REG; +} +reg_t kPaletteRestore(EngineState *s, int argc, reg_t *argv) { + if (g_sci->getResMan()->isVGA()) { + warning("kPalette(8), restore palette from heap STUB"); + } return s->r_acc; } -// This here is needed to make Pharkas work reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { - uint16 operation = argv[0].toUint16(); + if (!s) + return make_reg(0, getSciVersion()); + error("not supposed to call this"); +} - if (!g_sci->_gui) - return s->r_acc; +reg_t kPalVaryInit(EngineState *s, int argc, reg_t *argv) { + GuiResourceId paletteId = argv[0].toUint16(); + uint16 ticks = argv[1].toUint16(); + uint16 stepStop = argc >= 3 ? argv[2].toUint16() : 64; + uint16 direction = argc >= 4 ? argv[3].toUint16() : 1; + if (g_sci->_gfxPalette->kernelPalVaryInit(paletteId, ticks, stepStop, direction)) + return SIGNAL_REG; + return NULL_REG; +} - switch (operation) { - case 0: { // Init - GuiResourceId paletteId; - uint16 time; - if (argc == 3) { - paletteId = argv[1].toUint16(); - time = argv[2].toUint16(); - g_sci->_gfxPalette->startPalVary(paletteId, time); - warning("kPalVary(init) called with paletteId = %d, time = %d", paletteId, time); - } else { - warning("kPalVary(init) called with unsupported argc %d", argc); - } - break; - } - case 1: { // Unknown - warning("kPalVary(1) called with parameter %d (argc %d)", argv[1].toUint16(), argc); - break; - } - case 3: { // DeInit - if (argc == 1) { - g_sci->_gfxPalette->stopPalVary(); - warning("kPalVary(deinit)"); - } else { - warning("kPalVary(deinit) called with unsupported argc %d", argc); - } - break; - } - case 4: { // Unknown - warning("kPalVary(4) called with parameter %d (argc %d)", argv[1].toUint16(), argc); - break; - } - case 6: { // Pause - bool pauseState; - if (argc == 2) { - pauseState = argv[1].isNull() ? false : true; - g_sci->_gfxPalette->togglePalVary(pauseState); - warning("kPalVary(pause) called with state = %d", pauseState); - } else { - warning("kPalVary(pause) called with unsupported argc %d", argc); - } - break; - } - default: - warning("kPalVary(%d), not implemented (argc = %d)", operation, argc); - } +reg_t kPalVaryReverse(EngineState *s, int argc, reg_t *argv) { + int16 ticks = argc >= 1 ? argv[0].toUint16() : -1; + int16 stepStop = argc >= 2 ? argv[1].toUint16() : 0; + int16 direction = argc >= 3 ? argv[2].toSint16() : -1; + + return make_reg(0, g_sci->_gfxPalette->kernelPalVaryReverse(ticks, stepStop, direction)); +} + +reg_t kPalVaryGetCurrentStep(EngineState *s, int argc, reg_t *argv) { + return make_reg(0, g_sci->_gfxPalette->kernelPalVaryGetCurrentStep()); +} + +reg_t kPalVaryDeinit(EngineState *s, int argc, reg_t *argv) { + g_sci->_gfxPalette->kernelPalVaryDeinit(); + return NULL_REG; +} + +reg_t kPalVaryChangeTarget(EngineState *s, int argc, reg_t *argv) { + GuiResourceId paletteId = argv[0].toUint16(); + int16 currentStep = g_sci->_gfxPalette->kernelPalVaryChangeTarget(paletteId); + return make_reg(0, currentStep); +} + +reg_t kPalVaryChangeTicks(EngineState *s, int argc, reg_t *argv) { + uint16 ticks = argv[0].toUint16(); + g_sci->_gfxPalette->kernelPalVaryChangeTicks(ticks); + return NULL_REG; +} + +reg_t kPalVaryPauseResume(EngineState *s, int argc, reg_t *argv) { + bool pauseState = !argv[0].isNull(); + g_sci->_gfxPalette->kernelPalVaryPause(pauseState); + return NULL_REG; +} + +reg_t kPalVaryUnknown(EngineState *s, int argc, reg_t *argv) { + // Unknown (seems to be SCI32 exclusive) return NULL_REG; } reg_t kAssertPalette(EngineState *s, int argc, reg_t *argv) { - GuiResourceId paletteId = argv[1].toUint16(); + GuiResourceId paletteId = argv[0].toUint16(); g_sci->_gfxPalette->kernelAssertPalette(paletteId); return s->r_acc; @@ -698,9 +698,9 @@ reg_t kPortrait(EngineState *s, int argc, reg_t *argv) { case 0: { // load if (argc == 2) { Common::String resourceName = s->_segMan->getString(argv[1]); - s->r_acc = g_sci->_gui->portraitLoad(resourceName); + s->r_acc = g_sci->_gfxPaint16->kernelPortraitLoad(resourceName); } else { - warning("kPortrait(loadResource) called with unsupported argc %d", argc); + error("kPortrait(loadResource) called with unsupported argc %d", argc); } break; } @@ -715,24 +715,24 @@ reg_t kPortrait(EngineState *s, int argc, reg_t *argv) { uint seq = argv[8].toUint16() & 0xff; // argv[9] is usually 0??!! - g_sci->_gui->portraitShow(resourceName, position, resourceNum, noun, verb, cond, seq); + g_sci->_gfxPaint16->kernelPortraitShow(resourceName, position, resourceNum, noun, verb, cond, seq); return SIGNAL_REG; } else { - warning("kPortrait(show) called with unsupported argc %d", argc); + error("kPortrait(show) called with unsupported argc %d", argc); } break; } case 2: { // unload if (argc == 2) { uint16 portraitId = argv[1].toUint16(); - g_sci->_gui->portraitUnload(portraitId); + g_sci->_gfxPaint16->kernelPortraitUnload(portraitId); } else { - warning("kPortrait(unload) called with unsupported argc %d", argc); + error("kPortrait(unload) called with unsupported argc %d", argc); } break; } default: - warning("kPortrait(%d), not implemented (argc = %d)", operation, argc); + error("kPortrait(%d), not implemented (argc = %d)", operation, argc); } return s->r_acc; @@ -790,6 +790,11 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { mode = readSelectorValue(s->_segMan, controlObject, SELECTOR(mode)); maxChars = readSelectorValue(s->_segMan, controlObject, SELECTOR(max)); cursorPos = readSelectorValue(s->_segMan, controlObject, SELECTOR(cursor)); + if (cursorPos > (int)text.size()) { + // if cursor is outside of text, adjust accordingly + cursorPos = text.size(); + writeSelectorValue(s->_segMan, controlObject, SELECTOR(cursor), cursorPos); + } debugC(2, kDebugLevelGraphics, "drawing edit control %04x:%04x (text %04x:%04x, '%s') to %d,%d", PRINT_REG(controlObject), PRINT_REG(textReference), text.c_str(), x, y); g_sci->_gfxControls->kernelDrawTextEdit(rect, controlObject, g_sci->strSplit(text.c_str(), NULL).c_str(), fontId, mode, style, cursorPos, maxChars, hilite); return; @@ -801,11 +806,8 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { loopNo = (l & 0x80) ? l - 256 : l; int c = readSelectorValue(s->_segMan, controlObject, SELECTOR(cel)); celNo = (c & 0x80) ? c - 256 : c; - // Game-specific: *ONLY* the jones EGA/VGA sierra interpreter contain code using priority selector - // ALL other games use a hardcoded -1 (madness!) - // We are detecting jones/talkie as "jones" as well, but the sierra interpreter of talkie doesnt have this - // "hack". Hopefully it wont cause regressions (the code causes regressions if used against kq5/floppy) - if (!strcmp(g_sci->getGameID(), "jones")) + // Check if the control object specifies a priority selector (like in Jones) + if (lookupSelector(s->_segMan, controlObject, SELECTOR(priority), NULL, NULL) == kSelectorVariable) priority = readSelectorValue(s->_segMan, controlObject, SELECTOR(priority)); else priority = -1; @@ -821,12 +823,12 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { maxChars = readSelectorValue(s->_segMan, controlObject, SELECTOR(x)); // max chars per entry cursorOffset = readSelectorValue(s->_segMan, controlObject, SELECTOR(cursor)); - if (g_sci->getKernel()->_selectorCache.topString != -1) { + if (SELECTOR(topString) != -1) { // Games from early SCI1 onwards use topString upperOffset = readSelectorValue(s->_segMan, controlObject, SELECTOR(topString)); } else { // Earlier games use lsTop or brTop - if (lookupSelector(s->_segMan, controlObject, g_sci->getKernel()->_selectorCache.brTop, NULL, NULL) == kSelectorVariable) + if (lookupSelector(s->_segMan, controlObject, SELECTOR(brTop), NULL, NULL) == kSelectorVariable) upperOffset = readSelectorValue(s->_segMan, controlObject, SELECTOR(brTop)); else upperOffset = readSelectorValue(s->_segMan, controlObject, SELECTOR(lsTop)); @@ -883,6 +885,18 @@ reg_t kDrawControl(EngineState *s, int argc, reg_t *argv) { int state = readSelectorValue(s->_segMan, controlObject, SELECTOR(state)); writeSelectorValue(s->_segMan, controlObject, SELECTOR(state), (state | SCI_CONTROLS_STYLE_DISABLED) & ~SCI_CONTROLS_STYLE_ENABLED); } + if (objName == "DEdit") { + reg_t textReference = readSelector(s->_segMan, controlObject, SELECTOR(text)); + if (!textReference.isNull()) { + Common::String text = s->_segMan->getString(textReference); + if (text == "a:hq1_hero.sav") { + // Remove "a:" from hero quest export default filename + text.deleteChar(0); + text.deleteChar(0); + s->_segMan->strcpy(textReference, text.c_str()); + } + } + } _k_GenericDrawControl(s, controlObject, false); return NULL_REG; @@ -989,24 +1003,6 @@ reg_t kDrawCel(EngineState *s, int argc, reg_t *argv) { bool hiresMode = (argc > 7) ? true : false; reg_t upscaledHiresHandle = (argc > 7) ? argv[7] : NULL_REG; - if (!strcmp(g_sci->getGameID(), "freddypharkas") || !strcmp(g_sci->getGameID(), "freddypharkas-demo")) { - // WORKAROUND - // Script 24 contains code that draws the game menu on screen. It uses a temp variable for setting priority that - // is not set. in Sierra sci this happens to be 8250h. In our sci temporary variables are initialized thus we would - // get 0 here resulting in broken menus. - if ((viewId == 995) && (loopNo == 0) && (celNo == 0) && (priority == 0)) // game menu - priority = 15; - if ((viewId == 992) && (loopNo == 0) && (celNo == 0) && (priority == 0)) // quit game - priority = 15; - } - - if (!strcmp(g_sci->getGameID(), "laurabow2")) { - // WORKAROUND - // see the one above - if ((viewId == 995) && (priority == 0)) - priority = 15; - } - g_sci->_gfxPaint16->kernelDrawCel(viewId, loopNo, celNo, x, y, priority, paletteNo, hiresMode, upscaledHiresHandle); return s->r_acc; @@ -1049,10 +1045,6 @@ reg_t kAnimate(EngineState *s, int argc, reg_t *argv) { reg_t castListReference = (argc > 0) ? argv[0] : NULL_REG; bool cycle = (argc > 1) ? ((argv[1].toUint16()) ? true : false) : false; -#ifdef USE_OLD_MUSIC_FUNCTIONS - // Take care of incoming events (kAnimate is called semi-regularly) - process_sound_events(s); -#endif g_sci->_gfxAnimate->kernelAnimate(castListReference, cycle, argc, argv); return s->r_acc; @@ -1083,6 +1075,58 @@ reg_t kDisplay(EngineState *s, int argc, reg_t *argv) { return g_sci->_gfxPaint16->kernelDisplay(g_sci->strSplit(text.c_str()).c_str(), argc, argv); } +void playVideo(Graphics::VideoDecoder *videoDecoder) { + if (!videoDecoder) + return; + + byte *scaleBuffer = 0; + uint16 width = videoDecoder->getWidth(); + uint16 height = videoDecoder->getHeight(); + uint16 screenWidth = g_system->getWidth(); + uint16 screenHeight = g_system->getHeight(); + + if (screenWidth == 640 && width <= 320 && height <= 240) { + assert(videoDecoder->getPixelFormat().bytesPerPixel == 1); + width *= 2; + height *= 2; + scaleBuffer = new byte[width * height]; + } + + uint16 x = (screenWidth - width) / 2; + uint16 y = (screenHeight - height) / 2; + bool skipVideo = false; + + while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) { + if (videoDecoder->needsUpdate()) { + Graphics::Surface *frame = videoDecoder->decodeNextFrame(); + if (frame) { + if (scaleBuffer) { + // TODO: Probably should do aspect ratio correction in e.g. GK1 Windows + g_sci->_gfxScreen->scale2x((byte *)frame->pixels, scaleBuffer, videoDecoder->getWidth(), videoDecoder->getHeight()); + g_system->copyRectToScreen(scaleBuffer, width, x, y, width, height); + } else + g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, width, height); + + if (videoDecoder->hasDirtyPalette()) + videoDecoder->setSystemPalette(); + + g_system->updateScreen(); + } + } + + Common::Event event; + while (g_system->getEventManager()->pollEvent(event)) { + if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP) + skipVideo = true; + } + + g_system->delayMillis(10); + } + + delete[] scaleBuffer; + delete videoDecoder; +} + reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { // Hide the cursor if it's showing and then show it again if it was // previously visible. @@ -1106,7 +1150,7 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { initGraphics(screenWidth, screenHeight, screenWidth > 320, NULL); if (g_system->getScreenFormat().bytesPerPixel == 1) { - warning("This video requires >8bpp color to be displayed, but could not switch to RGB color mode."); + error("This video requires >8bpp color to be displayed, but could not switch to RGB color mode."); return NULL_REG; } @@ -1159,37 +1203,16 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { } if (videoDecoder) { - uint16 x = (screenWidth - videoDecoder->getWidth()) / 2; - uint16 y = (screenHeight - videoDecoder->getHeight()) / 2; - - while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo()) { - if (videoDecoder->needsUpdate()) { - Graphics::Surface *frame = videoDecoder->decodeNextFrame(); - if (frame) { - g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h); - - if (videoDecoder->hasDirtyPalette()) - videoDecoder->setSystemPalette(); - - g_system->updateScreen(); - } - } - - Common::Event event; - while (g_system->getEventManager()->pollEvent(event)) - ; - - g_system->delayMillis(10); - } + playVideo(videoDecoder); // HACK: Switch back to 8bpp if we played a QuickTime video. // We also won't be copying the screen to the SCI screen... if (g_system->getScreenFormat().bytesPerPixel != 1) initGraphics(screenWidth, screenHeight, screenWidth > 320); - else + else { g_sci->_gfxScreen->kernelSyncWithFramebuffer(); - - delete videoDecoder; + g_sci->_gfxPalette->kernelSyncScreenPalette(); + } } if (reshowCursor) @@ -1213,6 +1236,9 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) { warning("kRobot(init), id %d, obj %04x:%04x, flag %d, x=%d, y=%d", id, PRINT_REG(obj), flag, x, y); } break; + case 1: // LSL6 hires (startup) + // TODO + return NULL_REG; // an integer is expected case 4: { // start int id = argv[1].toUint16(); warning("kRobot(start), id %d", id); @@ -1228,30 +1254,140 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } + +reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { + uint16 operation = argv[0].toUint16(); + Graphics::VideoDecoder *videoDecoder = 0; + bool reshowCursor = g_sci->_gfxCursor->isVisible(); + Common::String fileName, warningMsg; + + switch (operation) { + case 0: // init + // This is actually meant to init the video file, but we play it instead + fileName = s->_segMan->derefString(argv[1]); + // TODO: argv[2] (usually null). When it exists, it points to an "Event" object, + // that holds no data initially (e.g. in the intro of Phantasmagoria 1 demo). + // Perhaps it's meant for syncing + if (argv[2] != NULL_REG) + warning("kPlayVMD: third parameter isn't 0 (it's %04x:%04x - %s)", PRINT_REG(argv[2]), s->_segMan->getObjectName(argv[2])); + + videoDecoder = new VMDDecoder(g_system->getMixer()); + + if (reshowCursor) + g_sci->_gfxCursor->kernelHide(); + + if (videoDecoder && videoDecoder->loadFile(fileName)) + playVideo(videoDecoder); + + if (reshowCursor) + g_sci->_gfxCursor->kernelShow(); + break; + case 1: + { + // Set VMD parameters. Called with a maximum of 6 parameters: + // + // x, y, flags, gammaBoost, gammaFirst, gammaLast + // + // Flags are as follows: + // bit 0 doubled + // bit 1 "drop frames"? + // bit 2 insert black lines + // bit 3 unknown + // bit 4 gamma correction + // bit 5 hold black frame + // bit 6 hold last frame + // bit 7 unknown + // bit 8 stretch + + // gammaBoost boosts palette colors in the range gammaFirst to + // gammaLast, but only if bit 4 in flags is set. Percent value such that + // 0% = no amplification These three parameters are optional if bit 4 is + // clear. Also note that the x, y parameters play subtle games if used + // with subfx 21. The subtleness has to do with creation of temporary + // planes and positioning relative to such planes. + + int flags = argv[3].offset; + Common::String flagspec; + + if (argc > 3) { + if (flags & 1) + flagspec += "doubled "; + if (flags & 2) + flagspec += "dropframes "; + if (flags & 4) + flagspec += "blacklines "; + if (flags & 8) + flagspec += "bit3 "; + if (flags & 16) + flagspec += "gammaboost "; + if (flags & 32) + flagspec += "holdblack "; + if (flags & 64) + flagspec += "holdlast "; + if (flags & 128) + flagspec += "bit7 "; + if (flags & 256) + flagspec += "stretch"; + + warning("VMDFlags: %s", flagspec.c_str()); + } + + warning("x, y: %d, %d", argv[1].offset, argv[2].offset); + + if (argc > 4 && flags & 16) + warning("gammaBoost: %d%% between palette entries %d and %d", argv[4].offset, argv[5].offset, argv[6].offset); + break; + } + case 6: + // Play, perhaps? Or stop? This is the last call made, and takes no extra parameters + case 14: + // Takes an additional integer parameter (e.g. 3) + case 16: + // Takes an additional parameter, usually 0 + case 21: + // Looks to be setting the video size and position. Called with 4 extra integer + // parameters (e.g. 86, 41, 235, 106) + default: + warningMsg = "PlayVMD - unsupported subop. Params: " + + Common::String::printf("%d", argc) + " ("; + + for (int i = 0; i < argc; i++) { + warningMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i])); + warningMsg += (i == argc - 1 ? ")" : ", "); + } + + warning("%s", warningMsg.c_str()); + break; + } + + return s->r_acc; +} + #endif reg_t kSetVideoMode(EngineState *s, int argc, reg_t *argv) { - // This call is used for KQ6's intro. It has one parameter, which is - // 1 when the intro begins, and 0 when it ends. It is suspected that - // this is actually a flag to enable video planar memory access, as - // the video decoder in KQ6 is specifically written for the planar - // memory model. Planar memory mode access was used for VGA "Mode X" - // (320x240 resolution, although the intro in KQ6 is 320x200). + // This call is used for KQ6's intro. It has one parameter, which is 1 when + // the intro begins, and 0 when it ends. It is suspected that this is + // actually a flag to enable video planar memory access, as the video + // decoder in KQ6 is specifically written for the planar memory model. + // Planar memory mode access was used for VGA "Mode X" (320x240 resolution, + // although the intro in KQ6 is 320x200). // Refer to http://en.wikipedia.org/wiki/Mode_X //warning("STUB: SetVideoMode %d", argv[0].toUint16()); return s->r_acc; } -// New calls for SCI11. Using those is only needed when using text-codes so that one is able to change -// font and/or color multiple times during kDisplay and kDrawControl +// New calls for SCI11. Using those is only needed when using text-codes so that +// one is able to change font and/or color multiple times during kDisplay and +// kDrawControl reg_t kTextFonts(EngineState *s, int argc, reg_t *argv) { - g_sci->_gui->textFonts(argc, argv); + g_sci->_gfxText16->kernelTextFonts(argc, argv); return s->r_acc; } reg_t kTextColors(EngineState *s, int argc, reg_t *argv) { - g_sci->_gui->textColors(argc, argv); + g_sci->_gfxText16->kernelTextColors(argc, argv); return s->r_acc; } diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index f06f3eec77..0701883a9b 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -37,12 +37,12 @@ static bool isSaneNodePointer(SegManager *segMan, reg_t addr) { Node *node = segMan->lookupNode(addr); if (!node) { - warning("isSaneNodePointer: Node at %04x:%04x wasn't found", PRINT_REG(addr)); + error("isSaneNodePointer: Node at %04x:%04x wasn't found", PRINT_REG(addr)); return false; } if (havePrev && node->pred != prev) { - warning("isSaneNodePointer: Node at %04x:%04x points to invalid predecessor %04x:%04x (should be %04x:%04x)", + error("isSaneNodePointer: Node at %04x:%04x points to invalid predecessor %04x:%04x (should be %04x:%04x)", PRINT_REG(addr), PRINT_REG(node->pred), PRINT_REG(prev)); //node->pred = prev; // fix the problem in the node @@ -58,33 +58,33 @@ static bool isSaneNodePointer(SegManager *segMan, reg_t addr) { } static void checkListPointer(SegManager *segMan, reg_t addr) { - List *l = segMan->lookupList(addr); + List *list = segMan->lookupList(addr); - if (!l) { - warning("isSaneListPointer (list %04x:%04x): The requested list wasn't found", + if (!list) { + error("checkListPointer (list %04x:%04x): The requested list wasn't found", PRINT_REG(addr)); return; } - if (l->first.isNull() && l->last.isNull()) { + if (list->first.isNull() && list->last.isNull()) { // Empty list is fine - } else if (!l->first.isNull() && !l->last.isNull()) { + } else if (!list->first.isNull() && !list->last.isNull()) { // Normal list - Node *node_a = segMan->lookupNode(l->first); - Node *node_z = segMan->lookupNode(l->last); + Node *node_a = segMan->lookupNode(list->first); + Node *node_z = segMan->lookupNode(list->last); if (!node_a) { - warning("isSaneListPointer (list %04x:%04x): missing first node", PRINT_REG(addr)); + error("checkListPointer (list %04x:%04x): missing first node", PRINT_REG(addr)); return; } if (!node_z) { - warning("isSaneListPointer (list %04x:%04x): missing last node", PRINT_REG(addr)); + error("checkListPointer (list %04x:%04x): missing last node", PRINT_REG(addr)); return; } if (!node_a->pred.isNull()) { - warning("isSaneListPointer (list %04x:%04x): First node of the list points to a predecessor node", + error("checkListPointer (list %04x:%04x): First node of the list points to a predecessor node", PRINT_REG(addr)); //node_a->pred = NULL_REG; // fix the problem in the node @@ -93,7 +93,7 @@ static void checkListPointer(SegManager *segMan, reg_t addr) { } if (!node_z->succ.isNull()) { - warning("isSaneListPointer (list %04x:%04x): Last node of the list points to a successor node", + error("checkListPointer (list %04x:%04x): Last node of the list points to a successor node", PRINT_REG(addr)); //node_z->succ = NULL_REG; // fix the problem in the node @@ -101,66 +101,42 @@ static void checkListPointer(SegManager *segMan, reg_t addr) { return; } - isSaneNodePointer(segMan, l->first); + isSaneNodePointer(segMan, list->first); } else { // Not sane list... it's missing pointers to the first or last element - if (l->first.isNull()) - warning("isSaneListPointer (list %04x:%04x): missing pointer to first element", + if (list->first.isNull()) + error("checkListPointer (list %04x:%04x): missing pointer to first element", PRINT_REG(addr)); - if (l->last.isNull()) - warning("isSaneListPointer (list %04x:%04x): missing pointer to last element", + if (list->last.isNull()) + error("checkListPointer (list %04x:%04x): missing pointer to last element", PRINT_REG(addr)); } } reg_t kNewList(EngineState *s, int argc, reg_t *argv) { - reg_t listbase; - List *l; - l = s->_segMan->allocateList(&listbase); - l->first = l->last = NULL_REG; - debugC(2, kDebugLevelNodes, "New listbase at %04x:%04x", PRINT_REG(listbase)); + reg_t listRef; + List *list = s->_segMan->allocateList(&listRef); + list->first = list->last = NULL_REG; + debugC(2, kDebugLevelNodes, "New listRef at %04x:%04x", PRINT_REG(listRef)); - return listbase; // Return list base address + return listRef; // Return list base address } reg_t kDisposeList(EngineState *s, int argc, reg_t *argv) { // This function is not needed in ScummVM. The garbage collector // cleans up unused objects automatically -#if 0 - List *l = s->_segMan->lookupList(argv[0]); - - if (!l) { - // FIXME: This should be an error, but it's turned to a warning for now - warning("Attempt to dispose non-list at %04x:%04x", PRINT_REG(argv[0])); - return NULL_REG; - } - - checkListPointer(s->_segMan, argv[0]); - - if (!l->first.isNull()) { - reg_t n_addr = l->first; - - while (!n_addr.isNull()) { // Free all nodes - Node *n = s->_segMan->lookupNode(n_addr); - n_addr = n->succ; - - //s->_segMan->free_Node(n_addr); // TODO - } - } - - //s->_segMan->free_list(argv[0]); // TODO -#endif - return s->r_acc; } reg_t kNewNode(EngineState *s, int argc, reg_t *argv) { reg_t nodeValue = argv[0]; - reg_t nodeKey = (argc == 2) ? argv[1] : NULL_REG; + // Some SCI32 games call this with 1 parameter (e.g. the demo of Phantasmagoria). + // Set the key to be the same as the value in this case + reg_t nodeKey = (argc == 2) ? argv[1] : argv[0]; s->r_acc = s->_segMan->newNode(nodeValue, nodeKey); - debugC(2, kDebugLevelNodes, "New nodebase at %04x:%04x", PRINT_REG(s->r_acc)); + debugC(2, kDebugLevelNodes, "New nodeRef at %04x:%04x", PRINT_REG(s->r_acc)); return s->r_acc; } @@ -169,11 +145,11 @@ reg_t kFirstNode(EngineState *s, int argc, reg_t *argv) { if (argv[0].isNull()) return NULL_REG; - List *l = s->_segMan->lookupList(argv[0]); + List *list = s->_segMan->lookupList(argv[0]); - if (l) { + if (list) { checkListPointer(s->_segMan, argv[0]); - return l->first; + return list->first; } else { return NULL_REG; } @@ -183,11 +159,11 @@ reg_t kLastNode(EngineState *s, int argc, reg_t *argv) { if (argv[0].isNull()) return NULL_REG; - List *l = s->_segMan->lookupList(argv[0]); + List *list = s->_segMan->lookupList(argv[0]); - if (l) { + if (list) { checkListPointer(s->_segMan, argv[0]); - return l->last; + return list->last; } else { return NULL_REG; } @@ -197,56 +173,56 @@ reg_t kEmptyList(EngineState *s, int argc, reg_t *argv) { if (argv[0].isNull()) return NULL_REG; - List *l = s->_segMan->lookupList(argv[0]); + List *list = s->_segMan->lookupList(argv[0]); checkListPointer(s->_segMan, argv[0]); - return make_reg(0, ((l) ? l->first.isNull() : 0)); + return make_reg(0, ((list) ? list->first.isNull() : 0)); } -static void _k_add_to_front(EngineState *s, reg_t listbase, reg_t nodebase) { - List *l = s->_segMan->lookupList(listbase); - Node *new_n = s->_segMan->lookupNode(nodebase); +static void addToFront(EngineState *s, reg_t listRef, reg_t nodeRef) { + List *list = s->_segMan->lookupList(listRef); + Node *newNode = s->_segMan->lookupNode(nodeRef); + + debugC(2, kDebugLevelNodes, "Adding node %04x:%04x to end of list %04x:%04x", PRINT_REG(nodeRef), PRINT_REG(listRef)); - debugC(2, kDebugLevelNodes, "Adding node %04x:%04x to end of list %04x:%04x", PRINT_REG(nodebase), PRINT_REG(listbase)); + if (!newNode) + error("Attempt to add non-node (%04x:%04x) to list at %04x:%04x", PRINT_REG(nodeRef), PRINT_REG(listRef)); + checkListPointer(s->_segMan, listRef); - // FIXME: This should be an error, but it's turned to a warning for now - if (!new_n) - warning("Attempt to add non-node (%04x:%04x) to list at %04x:%04x", PRINT_REG(nodebase), PRINT_REG(listbase)); - checkListPointer(s->_segMan, listbase); + newNode->pred = NULL_REG; + newNode->succ = list->first; - new_n->succ = l->first; - new_n->pred = NULL_REG; // Set node to be the first and last node if it's the only node of the list - if (l->first.isNull()) - l->last = nodebase; + if (list->first.isNull()) + list->last = nodeRef; else { - Node *old_n = s->_segMan->lookupNode(l->first); - old_n->pred = nodebase; + Node *oldNode = s->_segMan->lookupNode(list->first); + oldNode->pred = nodeRef; } - l->first = nodebase; + list->first = nodeRef; } -static void _k_add_to_end(EngineState *s, reg_t listbase, reg_t nodebase) { - List *l = s->_segMan->lookupList(listbase); - Node *new_n = s->_segMan->lookupNode(nodebase); +static void addToEnd(EngineState *s, reg_t listRef, reg_t nodeRef) { + List *list = s->_segMan->lookupList(listRef); + Node *newNode = s->_segMan->lookupNode(nodeRef); - debugC(2, kDebugLevelNodes, "Adding node %04x:%04x to end of list %04x:%04x", PRINT_REG(nodebase), PRINT_REG(listbase)); + debugC(2, kDebugLevelNodes, "Adding node %04x:%04x to end of list %04x:%04x", PRINT_REG(nodeRef), PRINT_REG(listRef)); - // FIXME: This should be an error, but it's turned to a warning for now - if (!new_n) - warning("Attempt to add non-node (%04x:%04x) to list at %04x:%04x", PRINT_REG(nodebase), PRINT_REG(listbase)); - checkListPointer(s->_segMan, listbase); + if (!newNode) + error("Attempt to add non-node (%04x:%04x) to list at %04x:%04x", PRINT_REG(nodeRef), PRINT_REG(listRef)); + checkListPointer(s->_segMan, listRef); + + newNode->pred = list->last; + newNode->succ = NULL_REG; - new_n->succ = NULL_REG; - new_n->pred = l->last; // Set node to be the first and last node if it's the only node of the list - if (l->last.isNull()) - l->first = nodebase; + if (list->last.isNull()) + list->first = nodeRef; else { - Node *old_n = s->_segMan->lookupNode(l->last); - old_n->succ = nodebase; + Node *old_n = s->_segMan->lookupNode(list->last); + old_n->succ = nodeRef; } - l->last = nodebase; + list->last = nodeRef; } reg_t kNextNode(EngineState *s, int argc, reg_t *argv) { @@ -274,28 +250,30 @@ reg_t kNodeValue(EngineState *s, int argc, reg_t *argv) { } reg_t kAddToFront(EngineState *s, int argc, reg_t *argv) { - _k_add_to_front(s, argv[0], argv[1]); + addToFront(s, argv[0], argv[1]); return s->r_acc; } reg_t kAddAfter(EngineState *s, int argc, reg_t *argv) { - List *l = s->_segMan->lookupList(argv[0]); + List *list = s->_segMan->lookupList(argv[0]); Node *firstnode = argv[1].isNull() ? NULL : s->_segMan->lookupNode(argv[1]); Node *newnode = s->_segMan->lookupNode(argv[2]); checkListPointer(s->_segMan, argv[0]); - // FIXME: This should be an error, but it's turned to a warning for now if (!newnode) { - warning("New 'node' %04x:%04x is not a node", PRINT_REG(argv[2])); + error("New 'node' %04x:%04x is not a node", PRINT_REG(argv[2])); return NULL_REG; } - if (argc != 3) { - warning("kAddAfter: Haven't got 3 arguments, aborting"); + if (argc != 3 && argc != 4) { + error("kAddAfter: Haven't got 3 or 4 arguments, aborting"); return NULL_REG; } + if (argc == 4) + newnode->key = argv[3]; + if (firstnode) { // We're really appending after reg_t oldnext = firstnode->succ; @@ -305,19 +283,19 @@ reg_t kAddAfter(EngineState *s, int argc, reg_t *argv) { if (oldnext.isNull()) // Appended after last node? // Set new node as last list node - l->last = argv[2]; + list->last = argv[2]; else s->_segMan->lookupNode(oldnext)->pred = argv[2]; } else { // !firstnode - _k_add_to_front(s, argv[0], argv[2]); // Set as initial list node + addToFront(s, argv[0], argv[2]); // Set as initial list node } return s->r_acc; } reg_t kAddToEnd(EngineState *s, int argc, reg_t *argv) { - _k_add_to_end(s, argv[0], argv[1]); + addToEnd(s, argv[0], argv[1]); return s->r_acc; } @@ -352,23 +330,27 @@ reg_t kFindKey(EngineState *s, int argc, reg_t *argv) { reg_t kDeleteKey(EngineState *s, int argc, reg_t *argv) { reg_t node_pos = kFindKey(s, 2, argv); Node *n; - List *l = s->_segMan->lookupList(argv[0]); + List *list = s->_segMan->lookupList(argv[0]); if (node_pos.isNull()) return NULL_REG; // Signal failure n = s->_segMan->lookupNode(node_pos); - if (l->first == node_pos) - l->first = n->succ; - if (l->last == node_pos) - l->last = n->pred; + if (list->first == node_pos) + list->first = n->succ; + if (list->last == node_pos) + list->last = n->pred; if (!n->pred.isNull()) s->_segMan->lookupNode(n->pred)->succ = n->succ; if (!n->succ.isNull()) s->_segMan->lookupNode(n->succ)->pred = n->pred; - //s->_segMan->free_Node(node_pos); // TODO + // Erase references to the predecessor and successor nodes, as the game + // scripts could reference the node itself again. + // Happens in the intro of QFG1 and in Longbow, when exiting the cave. + n->pred = NULL_REG; + n->succ = NULL_REG; return make_reg(0, 1); // Signal success } @@ -398,8 +380,6 @@ reg_t kSort(EngineState *s, int argc, reg_t *argv) { reg_t order_func = argv[2]; int input_size = (int16)readSelectorValue(segMan, source, SELECTOR(size)); - int i; - reg_t input_data = readSelector(segMan, source, SELECTOR(elements)); reg_t output_data = readSelector(segMan, dest, SELECTOR(elements)); @@ -422,9 +402,10 @@ reg_t kSort(EngineState *s, int argc, reg_t *argv) { sort_temp_t *temp_array = (sort_temp_t *)malloc(sizeof(sort_temp_t) * input_size); - i = 0; + int i = 0; while (node) { - invokeSelector(INV_SEL(s, order_func, doit, kStopOnInvalidSelector), 1, node->value); + reg_t params[1] = { node->value }; + invokeSelector(s, order_func, SELECTOR(doit), argc, argv, 1, params); temp_array[i].key = node->key; temp_array[i].value = node->value; temp_array[i].order = s->r_acc; @@ -436,7 +417,7 @@ reg_t kSort(EngineState *s, int argc, reg_t *argv) { for (i = 0;i < input_size;i++) { reg_t lNode = s->_segMan->newNode(temp_array[i].value, temp_array[i].key); - _k_add_to_end(s, output_data, lNode); + addToEnd(s, output_data, lNode); } free(temp_array); @@ -449,14 +430,14 @@ reg_t kSort(EngineState *s, int argc, reg_t *argv) { reg_t kListAt(EngineState *s, int argc, reg_t *argv) { if (argc != 2) { - warning("kListAt called with %d parameters", argc); + error("kListAt called with %d parameters", argc); return NULL_REG; } List *list = s->_segMan->lookupList(argv[0]); reg_t curAddress = list->first; if (list->first.isNull()) { - warning("kListAt tried to reference empty list (%04x:%04x)", PRINT_REG(argv[0])); + error("kListAt tried to reference empty list (%04x:%04x)", PRINT_REG(argv[0])); return NULL_REG; } Node *curNode = s->_segMan->lookupNode(curAddress); @@ -518,12 +499,12 @@ reg_t kListEachElementDo(EngineState *s, int argc, reg_t *argv) { if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) { // This can only happen with 3 params (list, target selector, variable) if (argc != 3) { - warning("kListEachElementDo: Attempted to modify a variable selector with %d params", argc); + error("kListEachElementDo: Attempted to modify a variable selector with %d params", argc); } else { writeSelector(s->_segMan, curObject, slc, argv[2]); } } else { - invokeSelectorArgv(s, curObject, slc, kContinueOnInvalidSelector, argc, argv, argc - 2, argv + 2); + invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2); } curNode = s->_segMan->lookupNode(nextNode); @@ -550,9 +531,9 @@ reg_t kListFirstTrue(EngineState *s, int argc, reg_t *argv) { // First, check if the target selector is a variable if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) { // Can this happen with variable selectors? - warning("kListFirstTrue: Attempted to access a variable selector"); + error("kListFirstTrue: Attempted to access a variable selector"); } else { - invokeSelectorArgv(s, curObject, slc, kContinueOnInvalidSelector, argc, argv, argc - 2, argv + 2); + invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2); // Check if the result is true if (!s->r_acc.isNull()) @@ -584,9 +565,9 @@ reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv) { // First, check if the target selector is a variable if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) { // Can this happen with variable selectors? - warning("kListAllTrue: Attempted to access a variable selector"); + error("kListAllTrue: Attempted to access a variable selector"); } else { - invokeSelectorArgv(s, curObject, slc, kContinueOnInvalidSelector, argc, argv, argc - 2, argv + 2); + invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2); // Check if the result isn't true if (s->r_acc.isNull()) @@ -627,15 +608,15 @@ reg_t kList(EngineState *s, int argc, reg_t *argv) { case 11: return kAddToEnd(s, argc - 1, argv + 1); case 12: - warning("kList: unimplemented subfunction kAddBefore"); + error("kList: unimplemented subfunction kAddBefore"); //return kAddBefore(s, argc - 1, argv + 1); return NULL_REG; case 13: - warning("kList: unimplemented subfunction kMoveToFront"); + error("kList: unimplemented subfunction kMoveToFront"); //return kMoveToFront(s, argc - 1, argv + 1); return NULL_REG; case 14: - warning("kList: unimplemented subfunction kMoveToEnd"); + error("kList: unimplemented subfunction kMoveToEnd"); //return kMoveToEnd(s, argc - 1, argv + 1); return NULL_REG; case 15: @@ -655,7 +636,7 @@ reg_t kList(EngineState *s, int argc, reg_t *argv) { case 22: return kSort(s, argc - 1, argv + 1); default: - warning("kList: Unhandled case %d", argv[0].toUint16()); + error("kList: Unhandled case %d", argv[0].toUint16()); return NULL_REG; } } diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp index dbf317860f..eab964d624 100644 --- a/engines/sci/engine/kmath.cpp +++ b/engines/sci/engine/kmath.cpp @@ -36,9 +36,6 @@ reg_t kRandom(EngineState *s, int argc, reg_t *argv) { } reg_t kAbs(EngineState *s, int argc, reg_t *argv) { - // This is a hack, but so is the code in Hoyle1 that needs it. - if (argv[0].segment) - return make_reg(0, 0x3e9); // Yes people, this is an object return make_reg(0, abs(argv[0].toSint16())); } @@ -112,7 +109,7 @@ reg_t kCosDiv(EngineState *s, int argc, reg_t *argv) { double cosval = cos(angle * PI / 180.0); if ((cosval < 0.0001) && (cosval > -0.0001)) { - warning("kCosDiv: Attempted division by zero"); + error("kCosDiv: Attempted division by zero"); return SIGNAL_REG; } else return make_reg(0, (int16)(value / cosval)); @@ -124,7 +121,7 @@ reg_t kSinDiv(EngineState *s, int argc, reg_t *argv) { double sinval = sin(angle * PI / 180.0); if ((sinval < 0.0001) && (sinval > -0.0001)) { - warning("kSinDiv: Attempted division by zero"); + error("kSinDiv: Attempted division by zero"); return SIGNAL_REG; } else return make_reg(0, (int16)(value / sinval)); @@ -136,7 +133,7 @@ reg_t kTimesTan(EngineState *s, int argc, reg_t *argv) { param -= 90; if ((param % 90) == 0) { - warning("kTimesTan: Attempted tan(pi/2)"); + error("kTimesTan: Attempted tan(pi/2)"); return SIGNAL_REG; } else return make_reg(0, (int16) - (tan(param * PI / 180.0) * scale)); @@ -147,10 +144,28 @@ reg_t kTimesCot(EngineState *s, int argc, reg_t *argv) { int scale = (argc > 1) ? argv[1].toSint16() : 1; if ((param % 90) == 0) { - warning("kTimesCot: Attempted tan(pi/2)"); + error("kTimesCot: Attempted tan(pi/2)"); return SIGNAL_REG; } else return make_reg(0, (int16)(tan(param * PI / 180.0) * scale)); } +#ifdef ENABLE_SCI32 + +reg_t kMulDiv(EngineState *s, int argc, reg_t *argv) { + int16 multiplicant = argv[0].toSint16(); + int16 multiplier = argv[1].toSint16(); + int16 denominator = argv[2].toSint16(); + + // Sanity check... + if (!denominator) { + error("kMulDiv: attempt to divide by zero (%d * %d / %d", multiplicant, multiplier, denominator); + return NULL_REG; + } + + return make_reg(0, multiplicant * multiplier / denominator); +} + +#endif + } // End of namespace Sci diff --git a/engines/sci/engine/kmenu.cpp b/engines/sci/engine/kmenu.cpp index a5f2f01297..c8a6e03556 100644 --- a/engines/sci/engine/kmenu.cpp +++ b/engines/sci/engine/kmenu.cpp @@ -27,7 +27,6 @@ #include "sci/resource.h" #include "sci/engine/state.h" #include "sci/engine/kernel.h" -#include "sci/graphics/gui.h" #include "sci/graphics/cursor.h" #include "sci/graphics/menu.h" @@ -74,7 +73,7 @@ reg_t kDrawStatus(EngineState *s, int argc, reg_t *argv) { int16 colorBack = (argc > 2) ? argv[2].toSint16() : g_sci->getResMan()->isVGA() ? 255 : 15; if (!textReference.isNull()) { - // Sometimes this is called without giving text, if thats the case dont process it + // Sometimes this is called without giving text, if thats the case dont process it. text = s->_segMan->getString(textReference); g_sci->_gfxMenu->kernelDrawStatus(g_sci->strSplit(text.c_str(), NULL).c_str(), colorPen, colorBack); @@ -91,10 +90,9 @@ reg_t kDrawMenuBar(EngineState *s, int argc, reg_t *argv) { reg_t kMenuSelect(EngineState *s, int argc, reg_t *argv) { reg_t eventObject = argv[0]; - //bool pauseSound = argc > 1 ? (argv[1].isNull() ? false : true) : false; + bool pauseSound = argc > 1 ? (argv[1].isNull() ? false : true) : true; - // TODO: pauseSound implementation - return g_sci->_gfxMenu->kernelSelect(eventObject); + return g_sci->_gfxMenu->kernelSelect(eventObject, pauseSound); } } // End of namespace Sci diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index f91ba0fd82..b8c62210f9 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -31,17 +31,14 @@ #include "sci/engine/state.h" #include "sci/engine/kernel.h" #include "sci/engine/gc.h" -#include "sci/graphics/gui.h" #include "sci/graphics/maciconbar.h" namespace Sci { reg_t kRestartGame(EngineState *s, int argc, reg_t *argv) { - s->restarting_flags |= SCI_GAME_IS_RESTARTING_NOW; - s->shrinkStackToBase(); - s->script_abort_flag = 1; // Force vm to abort ASAP + s->abortScriptProcessing = kAbortRestartGame; // Force vm to abort ASAP return NULL_REG; } @@ -49,47 +46,28 @@ reg_t kRestartGame(EngineState *s, int argc, reg_t *argv) { ** Returns the restarting_flag in acc */ reg_t kGameIsRestarting(EngineState *s, int argc, reg_t *argv) { - s->r_acc = make_reg(0, (s->restarting_flags & SCI_GAME_WAS_RESTARTED)); + s->r_acc = make_reg(0, s->gameWasRestarted); if (argc) { // Only happens during replay if (!argv[0].toUint16()) // Set restarting flag - s->restarting_flags &= ~SCI_GAME_WAS_RESTARTED; + s->gameWasRestarted = false; } uint32 neededSleep = 30; - // WORKAROUND: - // LSL3 calculates a machinespeed variable during game startup (right after the filthy questions) - // This one would go through w/o throttling resulting in having to do 1000 pushups or something - // Another way of handling this would be delaying incrementing of "machineSpeed" selector - if (!strcmp(g_sci->getGameID(), "lsl3") && s->currentRoomNumber() == 290) + // WORKAROUND: LSL3 calculates a machinespeed variable during game startup + // (right after the filthy questions). This one would go through w/o + // throttling resulting in having to do 1000 pushups or something. Another + // way of handling this would be delaying incrementing of "machineSpeed" + // selector. + if (g_sci->getGameId() == GID_LSL3 && s->currentRoomNumber() == 290) s->_throttleTrigger = true; - if (!strcmp(g_sci->getGameID(), "iceman") && s->currentRoomNumber() == 27) { + else if (g_sci->getGameId() == GID_ICEMAN && s->currentRoomNumber() == 27) { s->_throttleTrigger = true; neededSleep = 60; } - if (s->_throttleTrigger) { - // Some games seem to get the duration of main loop initially and then switch of animations for the whole game - // based on that (qfg2, iceman). We are now running full speed initially to avoid that. - // It seems like we dont need to do that anymore - //if (s->_throttleCounter < 50) { - // s->_throttleCounter++; - // return s->r_acc; - //} - - uint32 curTime = g_system->getMillis(); - uint32 duration = curTime - s->_throttleLastTime; - - if (duration < neededSleep) { - s->_event->sleep(neededSleep - duration); - s->_throttleLastTime = g_system->getMillis(); - } else { - s->_throttleLastTime = curTime; - } - s->_throttleTrigger = false; - } - + s->speedThrottler(neededSleep); return s->r_acc; } @@ -106,7 +84,11 @@ enum kMemoryInfoFunc { }; reg_t kMemoryInfo(EngineState *s, int argc, reg_t *argv) { - const uint16 size = 0x7fff; // Must not be 0xffff, or some memory calculations will overflow + // The free heap size returned must not be 0xffff, or some memory + // calculations will overflow. Crazy Nick's games handle up to 32746 + // bytes (0x7fea), otherwise they throw a warning that the memory is + // fragmented + const uint16 size = 0x7fea; switch (argv[0].offset) { case K_MEMORYINFO_LARGEST_HEAP_BLOCK: @@ -120,7 +102,7 @@ reg_t kMemoryInfo(EngineState *s, int argc, reg_t *argv) { return make_reg(0, size); default: - warning("Unknown MemoryInfo operation: %04x", argv[0].offset); + error("Unknown MemoryInfo operation: %04x", argv[0].offset); } return NULL_REG; @@ -172,8 +154,8 @@ reg_t kFlushResources(EngineState *s, int argc, reg_t *argv) { reg_t kSetDebug(EngineState *s, int argc, reg_t *argv) { printf("Debug mode activated\n"); - g_debugState.seeking = kDebugSeekNothing; - g_debugState.runningStep = 0; + g_sci->_debugState.seeking = kDebugSeekNothing; + g_sci->_debugState.runningStep = 0; return s->r_acc; } @@ -190,12 +172,12 @@ reg_t kGetTime(EngineState *s, int argc, reg_t *argv) { int retval = 0; // Avoid spurious warning g_system->getTimeAndDate(loc_time); - elapsedTime = g_system->getMillis() - s->game_start_time; + elapsedTime = g_system->getMillis() - s->gameStartTime; int mode = (argc > 0) ? argv[0].toUint16() : 0; if (getSciVersion() <= SCI_VERSION_0_LATE && mode > 1) - warning("kGetTime called in SCI0 with mode %d (expected 0 or 1)", mode); + error("kGetTime called in SCI0 with mode %d (expected 0 or 1)", mode); switch (mode) { case K_NEW_GETTIME_TICKS : @@ -215,7 +197,7 @@ reg_t kGetTime(EngineState *s, int argc, reg_t *argv) { debugC(2, kDebugLevelTime, "GetTime(date) returns %d", retval); break; default: - warning("Attempt to use unknown GetTime mode %d", mode); + error("Attempt to use unknown GetTime mode %d", mode); break; } @@ -261,7 +243,7 @@ reg_t kMemory(EngineState *s, int argc, reg_t *argv) { SegmentRef ref = s->_segMan->dereference(argv[1]); if (!ref.isValid() || ref.maxSize < 2) { - warning("Attempt to peek invalid memory at %04x:%04x", PRINT_REG(argv[1])); + error("Attempt to peek invalid memory at %04x:%04x", PRINT_REG(argv[1])); return s->r_acc; } if (ref.isRaw) @@ -277,7 +259,7 @@ reg_t kMemory(EngineState *s, int argc, reg_t *argv) { SegmentRef ref = s->_segMan->dereference(argv[1]); if (!ref.isValid() || ref.maxSize < 2) { - warning("Attempt to poke invalid memory at %04x:%04x", PRINT_REG(argv[1])); + error("Attempt to poke invalid memory at %04x:%04x", PRINT_REG(argv[1])); return s->r_acc; } @@ -335,11 +317,12 @@ reg_t kPlatform(EngineState *s, int argc, reg_t *argv) { bool isWindows = g_sci->getPlatform() == Common::kPlatformWindows; if (argc == 0 && getSciVersion() < SCI_VERSION_2) { - // This is called in KQ5CD with no parameters, where it seems to do some graphics - // driver check. This kernel function didn't have subfunctions then. If 0 is - // returned, the game functions normally, otherwise all the animations show up - // like a slideshow (e.g. in the intro). So we return 0. However, the behavior - // changed for kPlatform with no parameters in SCI32. + // This is called in KQ5CD with no parameters, where it seems to do some + // graphics driver check. This kernel function didn't have subfunctions + // then. If 0 is returned, the game functions normally, otherwise all + // the animations show up like a slideshow (e.g. in the intro). So we + // return 0. However, the behavior changed for kPlatform with no + // parameters in SCI32. return NULL_REG; } @@ -371,10 +354,18 @@ reg_t kPlatform(EngineState *s, int argc, reg_t *argv) { case kPlatformIsItWindows: return make_reg(0, isWindows); default: - warning("Unsupported kPlatform operation %d", operation); + error("Unsupported kPlatform operation %d", operation); } return NULL_REG; } +reg_t kEmpty(EngineState *s, int argc, reg_t *argv) { + // Placeholder for empty kernel functions which are still called from the + // engine scripts (like the empty kSetSynonyms function in SCI1.1). This + // differs from dummy functions because it does nothing and never throws a + // warning when it is called. + return s->r_acc; +} + } // End of namespace Sci diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp index 499aeabcc6..ccef3d862a 100644 --- a/engines/sci/engine/kmovement.cpp +++ b/engines/sci/engine/kmovement.cpp @@ -33,42 +33,43 @@ namespace Sci { -/* -Compute "velocity" vector (xStep,yStep)=(vx,vy) for a jump from (0,0) to (dx,dy), with gravity gy. -The gravity is assumed to be non-negative. - -If this was ordinary continuous physics, we would compute the desired (floating point!) -velocity vector (vx,vy) as follows, under the assumption that vx and vy are linearly correlated -by some constant factor c, i.e. vy = c * vx: - dx = t * vx - dy = t * vy + gy * t^2 / 2 -=> dy = c * dx + gy * (dx/vx)^2 / 2 -=> |vx| = sqrt( gy * dx^2 / (2 * (dy - c * dx)) ) -Here, the sign of vx must be chosen equal to the sign of dx, obviously. - -Clearly, this square root only makes sense in our context if the denominator is positive, -or equivalently, (dy - c * dx) must be positive. For simplicity and by symmetry -along the x-axis, we assume dx to be positive for all computations, and only adjust for -its sign in the end. Switching the sign of c appropriately, we set tmp := (dy + c * dx) -and compute c so that this term becomes positive. - -Remark #1: If the jump is straight up, i.e. dx == 0, then we should not assume the above -linear correlation vy = c * vx of the velocities (as vx will be 0, but vy shouldn't be, -unless we drop). - - -Remark #2: We are actually in a discrete setup. The motion is computed iteratively: each iteration, -we add vx and vy to the position, then add gy to vy. So the real formula is the following -(where t is ideally close to an int): - - dx = t * vx - dy = t * vy + gy * t*(t-1) / 2 - -But the solution resulting from that is a lot more complicated, so we use the above approximation instead. - -Still, what we compute in the end is of course not a real velocity anymore, but an integer approximation, -used in an iterative stepping algorithm -*/ +/** + * Compute "velocity" vector (xStep,yStep)=(vx,vy) for a jump from (0,0) to + * (dx,dy), with gravity constant gy. The gravity is assumed to be non-negative. + * + * If this was ordinary continuous physics, we would compute the desired + * (floating point!) velocity vector (vx,vy) as follows, under the assumption + * that vx and vy are linearly correlated by a constant c, i.e., vy = c * vx: + * dx = t * vx + * dy = t * vy + gy * t^2 / 2 + * => dy = c * dx + gy * (dx/vx)^2 / 2 + * => |vx| = sqrt( gy * dx^2 / (2 * (dy - c * dx)) ) + * Here, the sign of vx must be chosen equal to the sign of dx, obviously. + * + * This square root only makes sense in our context if the denominator is + * positive, or equivalently, (dy - c * dx) must be positive. For simplicity + * and by symmetry along the x-axis, we assume dx to be positive for all + * computations, and only adjust for its sign in the end. Switching the sign of + * c appropriately, we set tmp := (dy + c * dx) and compute c so that this term + * becomes positive. + * + * Remark #1: If the jump is straight up, i.e. dx == 0, then we should not + * assume the above linear correlation vy = c * vx of the velocities (as vx + * will be 0, but vy shouldn't be, unless we drop down). + * + * Remark #2: We are actually in a discrete setup. The motion is computed + * iteratively: each iteration, we add vx and vy to the position, then add gy + * to vy. So the real formula is the following (where t ideally is close to an int): + * + * dx = t * vx + * dy = t * vy + gy * t*(t-1) / 2 + * + * But the solution resulting from that is a lot more complicated, so we use + * the above approximation instead. + * + * Still, what we compute in the end is of course not a real velocity anymore, + * but an integer approximation, used in an iterative stepping algorithm. + */ reg_t kSetJump(EngineState *s, int argc, reg_t *argv) { SegManager *segMan = s->_segMan; // Input data @@ -115,7 +116,7 @@ reg_t kSetJump(EngineState *s, int argc, reg_t *argv) { //tmp = dx * 3 / 2; // ALMOST the resulting value, except for obvious rounding issues // FIXME: Where is the 3 coming from? Maybe they hard/coded, by "accident", that usually gy=3 ? - // Then this choice of will make t equal to roughly sqrt(dx) + // Then this choice of scalar will make t equal to roughly sqrt(dx) } } // POST: c >= 1 @@ -315,11 +316,11 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) { debugC(2, kDebugLevelBresen, "New data: (x,y)=(%d,%d), di=%d", x, y, bdi); - if (g_sci->getKernel()->_selectorCache.cantBeHere != -1) { - invokeSelector(INV_SEL(s, client, cantBeHere, kStopOnInvalidSelector), 0); + if (SELECTOR(cantBeHere) != -1) { + invokeSelector(s, client, SELECTOR(cantBeHere), argc, argv); s->r_acc = make_reg(0, !s->r_acc.offset); } else { - invokeSelector(INV_SEL(s, client, canBeHere, kStopOnInvalidSelector), 0); + invokeSelector(s, client, SELECTOR(canBeHere), argc, argv); } if (!s->r_acc.offset) { // Contains the return value @@ -335,7 +336,7 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) { if ((getSciVersion() >= SCI_VERSION_1_EGA)) if (completed) - invokeSelector(INV_SEL(s, mover, moveDone, kStopOnInvalidSelector), 0); + invokeSelector(s, mover, SELECTOR(moveDone), argc, argv); return make_reg(0, completed); } @@ -373,14 +374,14 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) { s->r_acc = SIGNAL_REG; if (!s->_segMan->isHeapObject(avoider)) { - warning("DoAvoider() where avoider %04x:%04x is not an object", PRINT_REG(avoider)); + error("DoAvoider() where avoider %04x:%04x is not an object", PRINT_REG(avoider)); return NULL_REG; } client = readSelector(segMan, avoider, SELECTOR(client)); if (!s->_segMan->isHeapObject(client)) { - warning("DoAvoider() where client %04x:%04x is not an object", PRINT_REG(client)); + error("DoAvoider() where client %04x:%04x is not an object", PRINT_REG(client)); return NULL_REG; } @@ -389,7 +390,7 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) { if (!s->_segMan->isHeapObject(mover)) { if (mover.segment) { - warning("DoAvoider() where mover %04x:%04x is not an object", PRINT_REG(mover)); + error("DoAvoider() where mover %04x:%04x is not an object", PRINT_REG(mover)); } return s->r_acc; } @@ -399,20 +400,13 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) { debugC(2, kDebugLevelBresen, "Doing avoider %04x:%04x (dest=%d,%d)", PRINT_REG(avoider), destx, desty); - if (invokeSelector(INV_SEL(s, mover, doit, kContinueOnInvalidSelector) , 0)) { - error("Mover %04x:%04x of avoider %04x:%04x doesn't have a doit() funcselector", PRINT_REG(mover), PRINT_REG(avoider)); - return NULL_REG; - } + invokeSelector(s, mover, SELECTOR(doit), argc, argv); mover = readSelector(segMan, client, SELECTOR(mover)); if (!mover.segment) // Mover has been disposed? return s->r_acc; // Return gracefully. - if (invokeSelector(INV_SEL(s, client, isBlocked, kContinueOnInvalidSelector) , 0)) { - error("Client %04x:%04x of avoider %04x:%04x doesn't" - " have an isBlocked() funcselector", PRINT_REG(client), PRINT_REG(avoider)); - return NULL_REG; - } + invokeSelector(s, client, SELECTOR(isBlocked), argc, argv); dx = destx - readSelectorValue(segMan, client, SELECTOR(x)); dy = desty - readSelectorValue(segMan, client, SELECTOR(y)); @@ -439,11 +433,7 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) { debugC(2, kDebugLevelBresen, "Pos (%d,%d): Trying angle %d; delta=(%d,%d)", oldx, oldy, angle, move_x, move_y); - if (invokeSelector(INV_SEL(s, client, canBeHere, kContinueOnInvalidSelector) , 0)) { - error("Client %04x:%04x of avoider %04x:%04x doesn't" - " have a canBeHere() funcselector", PRINT_REG(client), PRINT_REG(avoider)); - return NULL_REG; - } + invokeSelector(s, client, SELECTOR(canBeHere), argc, argv); writeSelectorValue(segMan, client, SELECTOR(x), oldx); writeSelectorValue(segMan, client, SELECTOR(y), oldy); @@ -461,7 +451,7 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) { angle -= 360; } - warning("DoAvoider failed for avoider %04x:%04x", PRINT_REG(avoider)); + error("DoAvoider failed for avoider %04x:%04x", PRINT_REG(avoider)); } else { int heading = readSelectorValue(segMan, client, SELECTOR(heading)); @@ -472,12 +462,11 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) { s->r_acc = make_reg(0, angle); + reg_t params[2] = { make_reg(0, angle), client }; + if (looper.segment) { - if (invokeSelector(INV_SEL(s, looper, doit, kContinueOnInvalidSelector), 2, angle, client)) { - error("Looper %04x:%04x of avoider %04x:%04x doesn't" - " have a doit() funcselector", PRINT_REG(looper), PRINT_REG(avoider)); - } else - return s->r_acc; + invokeSelector(s, looper, SELECTOR(doit), argc, argv, 2, params); + return s->r_acc; } else { // No looper? Fall back to DirLoop _k_dirloop(client, (uint16)angle, s, argc, argv); diff --git a/engines/sci/engine/kparse.cpp b/engines/sci/engine/kparse.cpp index 785ff39d22..45493a95d2 100644 --- a/engines/sci/engine/kparse.cpp +++ b/engines/sci/engine/kparse.cpp @@ -94,8 +94,8 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) { ResultWordList words; reg_t event = argv[1]; Vocabulary *voc = g_sci->getVocabulary(); - voc->parser_event = event; + reg_t params[2] = { voc->parser_base, stringpos }; bool res = voc->tokenizeString(words, string.c_str(), &error); voc->parserIsValid = false; /* not valid */ @@ -118,7 +118,7 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) { s->r_acc = make_reg(0, 1); writeSelectorValue(segMan, event, SELECTOR(claimed), 1); - invokeSelector(INV_SEL(s, s->_gameObj, syntaxFail, kStopOnInvalidSelector), 2, voc->parser_base, stringpos); + invokeSelector(s, g_sci->getGameObject(), SELECTOR(syntaxFail), argc, argv, 2, params); /* Issue warning */ debugC(2, kDebugLevelParser, "Tree building failed"); @@ -141,7 +141,7 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) { debugC(2, kDebugLevelParser, "Word unknown: %s", error); /* Issue warning: */ - invokeSelector(INV_SEL(s, s->_gameObj, wordFail, kStopOnInvalidSelector), 2, voc->parser_base, stringpos); + invokeSelector(s, g_sci->getGameObject(), SELECTOR(wordFail), argc, argv, 2, params); free(error); return make_reg(0, 1); /* Tell them that it didn't work */ } diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp index 857ccc2a08..fdaae3e121 100644 --- a/engines/sci/engine/kpathing.cpp +++ b/engines/sci/engine/kpathing.cpp @@ -436,33 +436,41 @@ static void print_input(EngineState *s, reg_t poly_list, Common::Point start, Co } } +/** + * Computes the area of a triangle + * Parameters: (const Common::Point &) a, b, c: The points of the triangle + * Returns : (int) The area multiplied by two + */ static int area(const Common::Point &a, const Common::Point &b, const Common::Point &c) { - // Computes the area of a triangle - // Parameters: (const Common::Point &) a, b, c: The points of the triangle - // Returns : (int) The area multiplied by two return (b.x - a.x) * (a.y - c.y) - (c.x - a.x) * (a.y - b.y); } +/** + * Determines whether or not a point is to the left of a directed line + * Parameters: (const Common::Point &) a, b: The directed line (a, b) + * (const Common::Point &) c: The query point + * Returns : (int) true if c is to the left of (a, b), false otherwise + */ static bool left(const Common::Point &a, const Common::Point &b, const Common::Point &c) { - // Determines whether or not a point is to the left of a directed line - // Parameters: (const Common::Point &) a, b: The directed line (a, b) - // (const Common::Point &) c: The query point - // Returns : (int) true if c is to the left of (a, b), false otherwise return area(a, b, c) > 0; } +/** + * Determines whether or not three points are collinear + * Parameters: (const Common::Point &) a, b, c: The three points + * Returns : (int) true if a, b, and c are collinear, false otherwise + */ static bool collinear(const Common::Point &a, const Common::Point &b, const Common::Point &c) { - // Determines whether or not three points are collinear - // Parameters: (const Common::Point &) a, b, c: The three points - // Returns : (int) true if a, b, and c are collinear, false otherwise return area(a, b, c) == 0; } +/** + * Determines whether or not a point lies on a line segment + * Parameters: (const Common::Point &) a, b: The line segment (a, b) + * (const Common::Point &) c: The query point + * Returns : (int) true if c lies on (a, b), false otherwise + */ static bool between(const Common::Point &a, const Common::Point &b, const Common::Point &c) { - // Determines whether or not a point lies on a line segment - // Parameters: (const Common::Point &) a, b: The line segment (a, b) - // (const Common::Point &) c: The query point - // Returns : (int) true if c lies on (a, b), false otherwise if (!collinear(a, b, c)) return false; @@ -473,25 +481,29 @@ static bool between(const Common::Point &a, const Common::Point &b, const Common return ((a.y <= c.y) && (c.y <= b.y)) || ((a.y >= c.y) && (c.y >= b.y)); } +/** + * Determines whether or not two line segments properly intersect + * Parameters: (const Common::Point &) a, b: The line segment (a, b) + * (const Common::Point &) c, d: The line segment (c, d) + * Returns : (int) true if (a, b) properly intersects (c, d), false otherwise + */ static bool intersect_proper(const Common::Point &a, const Common::Point &b, const Common::Point &c, const Common::Point &d) { - // Determines whether or not two line segments properly intersect - // Parameters: (const Common::Point &) a, b: The line segment (a, b) - // (const Common::Point &) c, d: The line segment (c, d) - // Returns : (int) true if (a, b) properly intersects (c, d), false otherwise int ab = (left(a, b, c) && left(b, a, d)) || (left(a, b, d) && left(b, a, c)); int cd = (left(c, d, a) && left(d, c, b)) || (left(c, d, b) && left(d, c, a)); return ab && cd; } +/** + * Polygon containment test + * Parameters: (const Common::Point &) p: The point + * (Polygon *) polygon: The polygon + * Returns : (int) CONT_INSIDE if p is strictly contained in polygon, + * CONT_ON_EDGE if p lies on an edge of polygon, + * CONT_OUTSIDE otherwise + * Number of ray crossing left and right + */ static int contained(const Common::Point &p, Polygon *polygon) { - // Polygon containment test - // Parameters: (const Common::Point &) p: The point - // (Polygon *) polygon: The polygon - // Returns : (int) CONT_INSIDE if p is strictly contained in polygon, - // CONT_ON_EDGE if p lies on an edge of polygon, - // CONT_OUTSIDE otherwise - // Number of ray crossing left and right int lcross = 0, rcross = 0; Vertex *vertex; @@ -549,10 +561,12 @@ static int contained(const Common::Point &p, Polygon *polygon) { return CONT_OUTSIDE; } +/** + * Computes polygon area + * Parameters: (Polygon *) polygon: The polygon + * Returns : (int) The area multiplied by two + */ static int polygon_area(Polygon *polygon) { - // Computes polygon area - // Parameters: (Polygon *) polygon: The polygon - // Returns : (int) The area multiplied by two Vertex *first = polygon->vertices.first(); Vertex *v; int size = 0; @@ -567,11 +581,13 @@ static int polygon_area(Polygon *polygon) { return size; } +/** + * Fixes the vertex order of a polygon if incorrect. Contained access + * polygons should have their vertices ordered clockwise, all other types + * anti-clockwise + * Parameters: (Polygon *) polygon: The polygon + */ static void fix_vertex_order(Polygon *polygon) { - // Fixes the vertex order of a polygon if incorrect. Contained access - // polygons should have their vertices ordered clockwise, all other types - // anti-clockwise - // Parameters: (Polygon *) polygon: The polygon int area = polygon_area(polygon); // When the polygon area is positive the vertices are ordered @@ -584,13 +600,15 @@ static void fix_vertex_order(Polygon *polygon) { } } +/** + * Determines whether or not a line from a point to a vertex intersects the + * interior of the polygon, locally at that vertex + * Parameters: (Common::Point) p: The point + * (Vertex *) vertex: The vertex + * Returns : (int) 1 if the line (p, vertex->v) intersects the interior of + * the polygon, locally at the vertex. 0 otherwise + */ static int inside(const Common::Point &p, Vertex *vertex) { - // Determines whether or not a line from a point to a vertex intersects the - // interior of the polygon, locally at that vertex - // Parameters: (Common::Point) p: The point - // (Vertex *) vertex: The vertex - // Returns : (int) 1 if the line (p, vertex->v) intersects the interior of - // the polygon, locally at the vertex. 0 otherwise // Check that it's not a single-vertex polygon if (VERTEX_HAS_EDGES(vertex)) { const Common::Point &prev = CLIST_PREV(vertex)->v; @@ -655,28 +673,34 @@ static VertexList *visible_vertices(PathfindingState *s, Vertex *vertex_cur) { return visVerts; } +/** + * Determines if a point lies on the screen border + * Parameters: (const Common::Point &) p: The point + * Returns : (int) true if p lies on the screen border, false otherwise + */ bool PathfindingState::pointOnScreenBorder(const Common::Point &p) { - // Determines if a point lies on the screen border - // Parameters: (const Common::Point &) p: The point - // Returns : (int) true if p lies on the screen border, false otherwise return (p.x == 0) || (p.x == _width - 1) || (p.y == 0) || (p.y == _height - 1); } +/** + * Determines if an edge lies on the screen border + * Parameters: (const Common::Point &) p, q: The edge (p, q) + * Returns : (int) true if (p, q) lies on the screen border, false otherwise + */ bool PathfindingState::edgeOnScreenBorder(const Common::Point &p, const Common::Point &q) { - // Determines if an edge lies on the screen border - // Parameters: (const Common::Point &) p, q: The edge (p, q) - // Returns : (int) true if (p, q) lies on the screen border, false otherwise return ((p.x == 0 && q.x == 0) || (p.y == 0 && q.y == 0) || ((p.x == _width - 1) && (q.x == _width - 1)) || ((p.y == _height - 1) && (q.y == _height - 1))); } +/** + * Searches for a nearby point that is not contained in a polygon + * Parameters: (FloatPoint) f: The pointf to search nearby + * (Polygon *) polygon: The polygon + * Returns : (int) PF_OK on success, PF_FATAL otherwise + * (Common::Point) *ret: The non-contained point on success + */ static int find_free_point(FloatPoint f, Polygon *polygon, Common::Point *ret) { - // Searches for a nearby point that is not contained in a polygon - // Parameters: (FloatPoint) f: The pointf to search nearby - // (Polygon *) polygon: The polygon - // Returns : (int) PF_OK on success, PF_FATAL otherwise - // (Common::Point) *ret: The non-contained point on success Common::Point p; // Try nearest point first @@ -706,12 +730,14 @@ static int find_free_point(FloatPoint f, Polygon *polygon, Common::Point *ret) { return PF_OK; } +/** + * Computes the near point of a point contained in a polygon + * Parameters: (const Common::Point &) p: The point + * (Polygon *) polygon: The polygon + * Returns : (int) PF_OK on success, PF_FATAL otherwise + * (Common::Point) *ret: The near point of p in polygon on success + */ int PathfindingState::findNearPoint(const Common::Point &p, Polygon *polygon, Common::Point *ret) { - // Computes the near point of a point contained in a polygon - // Parameters: (const Common::Point &) p: The point - // (Polygon *) polygon: The polygon - // Returns : (int) PF_OK on success, PF_FATAL otherwise - // (Common::Point) *ret: The near point of p in polygon on success Vertex *vertex; FloatPoint near_p; uint32 dist = HUGE_DISTANCE; @@ -751,13 +777,15 @@ int PathfindingState::findNearPoint(const Common::Point &p, Polygon *polygon, Co return find_free_point(near_p, polygon, ret); } +/** + * Computes the intersection point of a line segment and an edge (not + * including the vertices themselves) + * Parameters: (const Common::Point &) a, b: The line segment (a, b) + * (Vertex *) vertex: The first vertex of the edge + * Returns : (int) FP_OK on success, PF_ERROR otherwise + * (FloatPoint) *ret: The intersection point + */ static int intersection(const Common::Point &a, const Common::Point &b, Vertex *vertex, FloatPoint *ret) { - // Computes the intersection point of a line segment and an edge (not - // including the vertices themselves) - // Parameters: (const Common::Point &) a, b: The line segment (a, b) - // (Vertex *) vertex: The first vertex of the edge - // Returns : (int) FP_OK on success, PF_ERROR otherwise - // (FloatPoint) *ret: The intersection point // Parameters of parametric equations float s, t; // Numerator and denominator of equations @@ -790,16 +818,18 @@ static int intersection(const Common::Point &a, const Common::Point &b, Vertex * return PF_ERROR; } +/** + * Computes the nearest intersection point of a line segment and the polygon + * set. Intersection points that are reached from the inside of a polygon + * are ignored as are improper intersections which do not obstruct + * visibility + * Parameters: (PathfindingState *) s: The pathfinding state + * (const Common::Point &) p, q: The line segment (p, q) + * Returns : (int) PF_OK on success, PF_ERROR when no intersections were + * found, PF_FATAL otherwise + * (Common::Point) *ret: On success, the closest intersection point + */ static int nearest_intersection(PathfindingState *s, const Common::Point &p, const Common::Point &q, Common::Point *ret) { - // Computes the nearest intersection point of a line segment and the polygon - // set. Intersection points that are reached from the inside of a polygon - // are ignored as are improper intersections which do not obstruct - // visibility - // Parameters: (PathfindingState *) s: The pathfinding state - // (const Common::Point &) p, q: The line segment (p, q) - // Returns : (int) PF_OK on success, PF_ERROR when no intersections were - // found, PF_FATAL otherwise - // (Common::Point) *ret: On success, the closest intersection point Polygon *polygon = 0; FloatPoint isec; Polygon *ipolygon = 0; @@ -981,14 +1011,16 @@ static Common::Point *fixup_end_point(PathfindingState *s, const Common::Point & return new_end; } +/** + * Merges a point into the polygon set. A new vertex is allocated for this + * point, unless a matching vertex already exists. If the point is on an + * already existing edge that edge is split up into two edges connected by + * the new vertex + * Parameters: (PathfindingState *) s: The pathfinding state + * (const Common::Point &) v: The point to merge + * Returns : (Vertex *) The vertex corresponding to v + */ static Vertex *merge_point(PathfindingState *s, const Common::Point &v) { - // Merges a point into the polygon set. A new vertex is allocated for this - // point, unless a matching vertex already exists. If the point is on an - // already existing edge that edge is split up into two edges connected by - // the new vertex - // Parameters: (PathfindingState *) s: The pathfinding state - // (const Common::Point &) v: The point to merge - // Returns : (Vertex *) The vertex corresponding to v Vertex *vertex; Vertex *v_new; Polygon *polygon; @@ -1029,11 +1061,13 @@ static Vertex *merge_point(PathfindingState *s, const Common::Point &v) { return v_new; } +/** + * Converts an SCI polygon into a Polygon + * Parameters: (EngineState *) s: The game state + * (reg_t) polygon: The SCI polygon to convert + * Returns : (Polygon *) The converted polygon, or NULL on error + */ static Polygon *convert_polygon(EngineState *s, reg_t polygon) { - // Converts an SCI polygon into a Polygon - // Parameters: (EngineState *) s: The game state - // (reg_t) polygon: The SCI polygon to convert - // Returns : (Polygon *) The converted polygon, or NULL on error SegManager *segMan = s->_segMan; int i; reg_t points = readSelector(segMan, polygon, SELECTOR(points)); @@ -1056,7 +1090,7 @@ static Polygon *convert_polygon(EngineState *s, reg_t polygon) { // WORKAROUND: broken polygon in lsl1sci, room 350, after opening elevator // Polygon has 17 points but size is set to 19 - if ((size == 19) && !strcmp(g_sci->getGameID(), "lsl1sci")) { + if ((size == 19) && g_sci->getGameId() == GID_LSL1) { if ((s->currentRoomNumber() == 350) && (read_point(segMan, points, 18) == Common::Point(108, 137))) { debug(1, "Applying fix for broken polygon in lsl1sci, room 350"); @@ -1074,11 +1108,13 @@ static Polygon *convert_polygon(EngineState *s, reg_t polygon) { return poly; } +/** + * Changes the polygon list for optimization level 0 (used for keyboard + * support). Totally accessible polygons are removed and near-point + * accessible polygons are changed into totally accessible polygons. + * Parameters: (PathfindingState *) s: The pathfinding state + */ static void change_polygons_opt_0(PathfindingState *s) { - // Changes the polygon list for optimization level 0 (used for keyboard - // support). Totally accessible polygons are removed and near-point - // accessible polygons are changed into totally accessible polygons. - // Parameters: (PathfindingState *) s: The pathfinding state PolygonList::iterator it = s->polygons.begin(); while (it != s->polygons.end()) { @@ -1096,15 +1132,17 @@ static void change_polygons_opt_0(PathfindingState *s) { } } +/** + * Converts the SCI input data for pathfinding + * Parameters: (EngineState *) s: The game state + * (reg_t) poly_list: Polygon list + * (Common::Point) start: The start point + * (Common::Point) end: The end point + * (int) opt: Optimization level (0, 1 or 2) + * Returns : (PathfindingState *) On success a newly allocated pathfinding state, + * NULL otherwise + */ static PathfindingState *convert_polygon_set(EngineState *s, reg_t poly_list, Common::Point start, Common::Point end, int width, int height, int opt) { - // Converts the SCI input data for pathfinding - // Parameters: (EngineState *) s: The game state - // (reg_t) poly_list: Polygon list - // (Common::Point) start: The start point - // (Common::Point) end: The end point - // (int) opt: Optimization level (0, 1 or 2) - // Returns : (PathfindingState *) On success a newly allocated pathfinding state, - // NULL otherwise SegManager *segMan = s->_segMan; Polygon *polygon; int err; @@ -1174,7 +1212,7 @@ static PathfindingState *convert_polygon_set(EngineState *s, reg_t poly_list, Co // WORKAROUND LSL5 room 660. Priority glitch due to us choosing a different path // than SSCI. Happens when Patti walks to the control room. - if (!strcmp(g_sci->getGameID(), "lsl5") && (s->currentRoomNumber() == 660) && (Common::Point(67, 131) == *new_start) && (Common::Point(229, 101) == *new_end)) { + if (g_sci->getGameId() == GID_LSL5 && (s->currentRoomNumber() == 660) && (Common::Point(67, 131) == *new_start) && (Common::Point(229, 101) == *new_end)) { debug(1, "[avoidpath] Applying fix for priority problem in LSL5, room 660"); pf_s->_prependPoint = new_start; new_start = new Common::Point(77, 107); @@ -1297,11 +1335,13 @@ static reg_t allocateOutputArray(SegManager *segMan, int size) { return addr; } +/** + * Stores the final path in newly allocated dynmem + * Parameters: (PathfindingState *) p: The pathfinding state + * (EngineState *) s: The game state + * Returns : (reg_t) Pointer to dynmem containing path + */ static reg_t output_path(PathfindingState *p, EngineState *s) { - // Stores the final path in newly allocated dynmem - // Parameters: (PathfindingState *) p: The pathfinding state - // (EngineState *) s: The game state - // Returns : (reg_t) Pointer to dynmem containing path int path_len = 0; reg_t output; Vertex *vertex = p->vertex_end; @@ -1694,17 +1734,14 @@ reg_t kIntersections(EngineState *s, int argc, reg_t *argv) { } } -// This is a quite rare kernel function. An example of when it's called -// is in QFG1VGA, after killing any monster. +/** + * This is a quite rare kernel function. An example of when it's called + * is in QFG1VGA, after killing any monster. + */ reg_t kMergePoly(EngineState *s, int argc, reg_t *argv) { +#if 0 // 3 parameters: raw polygon data, polygon list, list size reg_t polygonData = argv[0]; - - // TODO: actually merge the polygon - // In QFG1VGA, there are no immediately visible side-effects - // of this being a stub. - -#if 0 List *list = s->_segMan->lookupList(argv[1]); Node *node = s->_segMan->lookupNode(list->first); // List size is not needed @@ -1723,9 +1760,14 @@ reg_t kMergePoly(EngineState *s, int argc, reg_t *argv) { } #endif + // TODO: actually merge the polygon. We return an empty polygon for now. + // In QFG1VGA, you can walk over enemy bodies after killing them, since + // this is a stub. + reg_t output = allocateOutputArray(s->_segMan, 1); + SegmentRef arrayRef = s->_segMan->dereference(output); + writePoint(arrayRef, 0, Common::Point(POLY_LAST_POINT, POLY_LAST_POINT)); warning("Stub: kMergePoly"); - - return polygonData; + return output; } } // End of namespace Sci diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index 722d0175d1..029943b070 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -25,16 +25,20 @@ #include "sci/sci.h" #include "sci/resource.h" +#include "sci/engine/seg_manager.h" +#include "sci/engine/script.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/engine/kernel.h" +#include "common/file.h" + namespace Sci { // Loads arbitrary resources of type 'restype' with resource numbers 'resnrs' // This implementation ignores all resource numbers except the first one. reg_t kLoad(EngineState *s, int argc, reg_t *argv) { - int restype = argv[0].toUint16(); + ResourceType restype = (ResourceType)(argv[0].toUint16() & 0x7f); int resnr = argv[1].toUint16(); // Request to dynamically allocate hunk memory for later use @@ -44,6 +48,29 @@ reg_t kLoad(EngineState *s, int argc, reg_t *argv) { return make_reg(0, ((restype << 11) | resnr)); // Return the resource identifier as handle } +// Unloads an arbitrary resource of type 'restype' with resource numbber 'resnr' +// behaviour of this call didn't change between sci0->sci1.1 parameter wise, which means getting called with +// 1 or 3+ parameters is not right according to sierra sci +reg_t kUnLoad(EngineState *s, int argc, reg_t *argv) { + if (argc >= 2) { + ResourceType restype = (ResourceType)(argv[0].toUint16() & 0x7f); + reg_t resnr = argv[1]; + + // WORKAROUND for a broken script in room 320 in Castle of Dr. Brain. + // Script 377 tries to free the hunk memory allocated for the saved area + // (underbits) beneath the pop up window, which results in having the + // window stay on screen even when it's closed. Ignore this request here. + if (restype == kResourceTypeMemory && g_sci->getGameId() == GID_CASTLEBRAIN && + s->currentRoomNumber() == 320) + return s->r_acc; + + if (restype == kResourceTypeMemory) + s->_segMan->freeHunkEntry(resnr); + } + + return s->r_acc; +} + reg_t kLock(EngineState *s, int argc, reg_t *argv) { int state = argc > 2 ? argv[2].toUint16() : 1; ResourceType type = (ResourceType)(argv[0].toUint16() & 0x7f); @@ -56,43 +83,46 @@ reg_t kLock(EngineState *s, int argc, reg_t *argv) { g_sci->getResMan()->findResource(id, 1); break; case 0 : - which = g_sci->getResMan()->findResource(id, 0); - - if (which) - g_sci->getResMan()->unlockResource(which); - else { - if (id.type == kResourceTypeInvalid) - warning("[resMan] Attempt to unlock resource %i of invalid type %i", id.number, type); - else - warning("[resMan] Attempt to unlock non-existant resource %s", id.toString().c_str()); + if (id.getNumber() == 0xFFFF) { + // Unlock all resources of the requested type + Common::List<ResourceId> *resources = g_sci->getResMan()->listResources(type); + Common::List<ResourceId>::iterator itr = resources->begin(); + + while (itr != resources->end()) { + Resource *res = g_sci->getResMan()->testResource(*itr); + if (res->isLocked()) + g_sci->getResMan()->unlockResource(res); + ++itr; + } + + } else { + which = g_sci->getResMan()->findResource(id, 0); + + if (which) + g_sci->getResMan()->unlockResource(which); + else { + if (id.getType() == kResourceTypeInvalid) + warning("[resMan] Attempt to unlock resource %i of invalid type %i", id.getNumber(), type); + else + // Happens in CD games (e.g. LSL6CD) with the message resource + warning("[resMan] Attempt to unlock non-existant resource %s", id.toString().c_str()); + } } break; } return s->r_acc; } -// Unloads an arbitrary resource of type 'restype' with resource numbber 'resnr' -reg_t kUnLoad(EngineState *s, int argc, reg_t *argv) { - if (argc >= 2) { - int restype = argv[0].toUint16(); - reg_t resnr = argv[1]; - - if (restype == kResourceTypeMemory) - s->_segMan->freeHunkEntry(resnr); - - if (argc > 2) - warning("kUnload called with more than 2 parameters (%d)", argc); - } else { - warning("kUnload called with less than 2 parameters (%d) - ignoring", argc); - } - - return s->r_acc; -} - reg_t kResCheck(EngineState *s, int argc, reg_t *argv) { Resource *res = NULL; ResourceType restype = (ResourceType)(argv[0].toUint16() & 0x7f); + if (restype == kResourceTypeVMD) { + char fileName[10]; + sprintf(fileName, "%d.vmd", argv[1].toUint16()); + return make_reg(0, Common::File::exists(fileName)); + } + if ((restype == kResourceTypeAudio36) || (restype == kResourceTypeSync36)) { if (argc >= 6) { uint noun = argv[2].toUint16() & 0xff; @@ -155,24 +185,10 @@ reg_t kDisposeClone(EngineState *s, int argc, reg_t *argv) { } if (!victim_obj->isClone()) { - //warning("Attempt to dispose something other than a clone at %04x", offset); // SCI silently ignores this behaviour; some games actually depend on it return s->r_acc; } - // QFG3 clears clones with underbits set - //if (readSelectorValue(victim_addr, underBits)) - // warning("Clone %04x:%04x was cleared with underBits set", PRINT_REG(victim_addr)); - -#if 0 - if (s->dyn_views) { // Free any widget associated with the clone - GfxWidget *widget = gfxw_set_id(gfxw_remove_ID(s->dyn_views, offset), GFXW_NO_ID); - - if (widget && s->bg_widgets) - s->bg_widgets->add(GFXWC(s->bg_widgets), widget); - } -#endif - victim_obj->markAsFreed(); return s->r_acc; @@ -198,9 +214,10 @@ reg_t kScriptID(EngineState *s, int argc, reg_t *argv) { // and this call is probably used to load them in memory, ignoring // the return value. If only one argument is passed, this call is done // only to load the script in memory. Thus, don't show any warning, - // as no return value is expected + // as no return value is expected. If an export is requested, then + // it will most certainly fail with OOB access. if (argc == 2) - warning("Script 0x%x does not have a dispatch table and export %d " + error("Script 0x%x does not have a dispatch table and export %d " "was requested from it", script, index); return NULL_REG; } @@ -222,10 +239,6 @@ reg_t kScriptID(EngineState *s, int argc, reg_t *argv) { reg_t kDisposeScript(EngineState *s, int argc, reg_t *argv) { int script = argv[0].offset; - // Work around QfG1 graveyard bug - if (argv[0].segment) - return s->r_acc; - SegmentId id = s->_segMan->getScriptSegment(script); Script *scr = s->_segMan->getScriptIfLoaded(id); if (scr) { @@ -233,13 +246,13 @@ reg_t kDisposeScript(EngineState *s, int argc, reg_t *argv) { scr->setLockers(1); } - script_uninstantiate(s->_segMan, script); + s->_segMan->uninstantiateScript(script); if (argc != 2) { return s->r_acc; } else { - // This exists in the KQ5CD and GK1 interpreter. We know it is used when GK1 starts - // up, before the Sierra logo. + // This exists in the KQ5CD and GK1 interpreter. We know it is used + // when GK1 starts up, before the Sierra logo. warning("kDisposeScript called with 2 parameters, still untested"); return argv[1]; } diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index 367a89005c..69ae68674b 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -39,12 +39,38 @@ namespace Sci { * Used for synthesized music playback */ reg_t kDoSound(EngineState *s, int argc, reg_t *argv) { - return s->_soundCmd->parseCommand(argc, argv, s->r_acc); + if (!s) + return make_reg(0, g_sci->_features->detectDoSoundType()); + error("not supposed to call this"); } +#define CREATE_DOSOUND_FORWARD(_name_) reg_t k##_name_(EngineState *s, int argc, reg_t *argv) { return g_sci->_soundCmd->k##_name_(argc, argv, s->r_acc); } + +CREATE_DOSOUND_FORWARD(DoSoundInit) +CREATE_DOSOUND_FORWARD(DoSoundPlay) +CREATE_DOSOUND_FORWARD(DoSoundDummy) +CREATE_DOSOUND_FORWARD(DoSoundDispose) +CREATE_DOSOUND_FORWARD(DoSoundMute) +CREATE_DOSOUND_FORWARD(DoSoundStop) +CREATE_DOSOUND_FORWARD(DoSoundStopAll) +CREATE_DOSOUND_FORWARD(DoSoundPause) +CREATE_DOSOUND_FORWARD(DoSoundResume) +CREATE_DOSOUND_FORWARD(DoSoundMasterVolume) +CREATE_DOSOUND_FORWARD(DoSoundUpdate) +CREATE_DOSOUND_FORWARD(DoSoundFade) +CREATE_DOSOUND_FORWARD(DoSoundGetPolyphony) +CREATE_DOSOUND_FORWARD(DoSoundUpdateCues) +CREATE_DOSOUND_FORWARD(DoSoundSendMidi) +CREATE_DOSOUND_FORWARD(DoSoundReverb) +CREATE_DOSOUND_FORWARD(DoSoundSetHold) +CREATE_DOSOUND_FORWARD(DoSoundGetAudioCapability) +CREATE_DOSOUND_FORWARD(DoSoundSuspend) +CREATE_DOSOUND_FORWARD(DoSoundSetVolume) +CREATE_DOSOUND_FORWARD(DoSoundSetPriority) +CREATE_DOSOUND_FORWARD(DoSoundSetLoop) + reg_t kDoCdAudio(EngineState *s, int argc, reg_t *argv) { switch (argv[0].toUint16()) { - case kSciAudioWPlay: case kSciAudioPlay: { if (argc < 2) return NULL_REG; @@ -72,6 +98,7 @@ reg_t kDoCdAudio(EngineState *s, int argc, reg_t *argv) { break; case kSciAudioPosition: return make_reg(0, g_sci->_audio->audioCdPosition()); + case kSciAudioWPlay: // CD Audio can't be preloaded case kSciAudioRate: // No need to set the audio rate case kSciAudioVolume: // The speech setting isn't used by CD Audio case kSciAudioLanguage: // No need to set the language @@ -80,7 +107,7 @@ reg_t kDoCdAudio(EngineState *s, int argc, reg_t *argv) { // Init return make_reg(0, 1); default: - warning("kCdDoAudio: Unhandled case %d", argv[0].toUint16()); + error("kCdDoAudio: Unhandled case %d", argv[0].toUint16()); } return s->r_acc; @@ -110,8 +137,10 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) { number = argv[1].toUint16(); } else if (argc == 6 || argc == 8) { module = argv[1].toUint16(); - number = ((argv[2].toUint16() & 0xff) << 24) | ((argv[3].toUint16() & 0xff) << 16) | - ((argv[4].toUint16() & 0xff) << 8) | (argv[5].toUint16() & 0xff); + number = ((argv[2].toUint16() & 0xff) << 24) | + ((argv[3].toUint16() & 0xff) << 16) | + ((argv[4].toUint16() & 0xff) << 8) | + (argv[5].toUint16() & 0xff); if (argc == 8) warning("kDoAudio: Play called with SQ6 extra parameters"); } else { @@ -119,46 +148,91 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } - return make_reg(0, g_sci->_audio->startAudio(module, number)); // return sample length in ticks + debugC(2, kDebugLevelSound, "kDoAudio: play sample %d, module %d", number, module); + + // return sample length in ticks + if (argv[0].toUint16() == kSciAudioWPlay) + return make_reg(0, g_sci->_audio->wPlayAudio(module, number)); + else + return make_reg(0, g_sci->_audio->startAudio(module, number)); } case kSciAudioStop: + debugC(2, kDebugLevelSound, "kDoAudio: stop"); g_sci->_audio->stopAudio(); break; case kSciAudioPause: + debugC(2, kDebugLevelSound, "kDoAudio: pause"); g_sci->_audio->pauseAudio(); break; case kSciAudioResume: + debugC(2, kDebugLevelSound, "kDoAudio: resume"); g_sci->_audio->resumeAudio(); break; case kSciAudioPosition: + //debugC(2, kDebugLevelSound, "kDoAudio: get position"); // too verbose return make_reg(0, g_sci->_audio->getAudioPosition()); case kSciAudioRate: + debugC(2, kDebugLevelSound, "kDoAudio: set audio rate to %d", argv[1].toUint16()); g_sci->_audio->setAudioRate(argv[1].toUint16()); break; case kSciAudioVolume: { int16 volume = argv[1].toUint16(); volume = CLIP<int16>(volume, 0, AUDIO_VOLUME_MAX); + debugC(2, kDebugLevelSound, "kDoAudio: set volume to %d", volume); +#ifdef ENABLE_SCI32 + if (getSciVersion() >= SCI_VERSION_2_1) { + int16 volumePrev = mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType) / 2; + volumePrev = CLIP<int16>(volumePrev, 0, AUDIO_VOLUME_MAX); + mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume * 2); + return make_reg(0, volumePrev); + } else +#endif mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume * 2); - break; } case kSciAudioLanguage: // In SCI1.1: tests for digital audio support - if (getSciVersion() == SCI_VERSION_1_1) + if (getSciVersion() == SCI_VERSION_1_1) { + debugC(2, kDebugLevelSound, "kDoAudio: audio capability test"); return make_reg(0, 1); - else { + } else { int16 language = argv[1].toSint16(); + debugC(2, kDebugLevelSound, "kDoAudio: set language to %d", language); if (language != -1) g_sci->getResMan()->setAudioLanguage(language); - return make_reg(0, g_sci->getSciLanguage()); + kLanguage kLang = g_sci->getSciLanguage(); + g_sci->setSciLanguage(kLang); + + return make_reg(0, kLang); } break; case kSciAudioCD: - return kDoCdAudio(s, argc - 1, argv + 1); - // TODO: There are 3 more functions used in Freddy Pharkas (11, 12 and 13) and new within sierra sci - // Details currently unknown - // kDoAudio sits at seg026:038C + + if (getSciVersion() <= SCI_VERSION_1_1) { + debugC(2, kDebugLevelSound, "kDoAudio: CD audio subop"); + return kDoCdAudio(s, argc - 1, argv + 1); +#ifdef ENABLE_SCI32 + } else { + // TODO: This isn't CD Audio in SCI32 anymore + warning("kDoAudio: Unhandled case 10, %d extra arguments passed", argc - 1); + break; +#endif + } + + // 3 new subops in Pharkas. kDoAudio in Pharkas sits at seg026:038C + case 11: + warning("kDoAudio: Unhandled case 11, %d extra arguments passed", argc - 1); + break; + case 12: + // Seems to be audio sync, used in Pharkas. Silenced the warning due to + // the high level of spam it produces. + //warning("kDoAudio: Unhandled case 12, %d extra arguments passed", argc - 1); + break; + case 13: + // Used in Pharkas whenever a speech sample starts + warning("kDoAudio: Unhandled case 13, %d extra arguments passed", argc - 1); + break; default: warning("kDoAudio: Unhandled case %d, %d extra arguments passed", argv[0].toUint16(), argc - 1); } @@ -195,7 +269,7 @@ reg_t kDoSync(EngineState *s, int argc, reg_t *argv) { g_sci->_audio->stopSoundSync(); break; default: - warning("DoSync: Unhandled subfunction %d", argv[0].toUint16()); + error("DoSync: Unhandled subfunction %d", argv[0].toUint16()); } return s->r_acc; diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index 2681b612e9..f2f9543ad2 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -115,12 +115,14 @@ reg_t kStrAt(EngineState *s, int argc, reg_t *argv) { if (argc > 2) { /* Request to modify this char */ tmp.offset &= 0xff00; tmp.offset |= newvalue; + tmp.segment = 0; } } else { value = tmp.offset >> 8; if (argc > 2) { /* Request to modify this char */ tmp.offset &= 0x00ff; tmp.offset |= newvalue << 8; + tmp.segment = 0; } } } @@ -141,19 +143,22 @@ reg_t kReadNumber(EngineState *s, int argc, reg_t *argv) { int16 result = 0; if (*source == '$') { - // hexadecimal input + // Hexadecimal input result = (int16)strtol(source + 1, NULL, 16); } else { - // decimal input, we can not use strtol/atoi in here, because sierra used atoi BUT it was a non standard compliant - // atoi, that didnt do clipping. In SQ4 we get the door code in here and that's even larger than uint32! + // Decimal input. We can not use strtol/atoi in here, because while + // Sierra used atoi, it was a non standard compliant atoi, that didn't + // do clipping. In SQ4 we get the door code in here and that's even + // larger than uint32! if (*source == '-') { result = -1; source++; } while (*source) { if ((*source < '0') || (*source > '9')) { - // Sierras atoi stopped processing at anything different than number - // Sometimes the input has a trailing space, that's fine (example: lsl3) + // Sierra's atoi stopped processing at anything which is not + // a digit. Sometimes the input has a trailing space, that's + // fine (example: lsl3) if (*source != ' ') { // TODO: this happens in lsl5 right in the intro -> we get '1' '3' 0xCD 0xCD 0xCD 0xCD 0xCD // find out why this happens and fix it @@ -423,15 +428,16 @@ reg_t kGetFarText(EngineState *s, int argc, reg_t *argv) { seeker = (char *)textres->data; - // The second parameter (counter) determines the number of the string inside the text - // resource. + // The second parameter (counter) determines the number of the string + // inside the text resource. while (counter--) { while (*seeker++) ; } - // If the third argument is NULL, allocate memory for the destination. This occurs in - // SCI1 Mac games. The memory will later be freed by the game's scripts. + // If the third argument is NULL, allocate memory for the destination. This + // occurs in SCI1 Mac games. The memory will later be freed by the game's + // scripts. if (argv[2] == NULL_REG) s->_segMan->allocDynmem(strlen(seeker) + 1, "Mac FarText", &argv[2]); @@ -561,7 +567,7 @@ reg_t kMessage(EngineState *s, int argc, reg_t *argv) { reg_t kSetQuitStr(EngineState *s, int argc, reg_t *argv) { Common::String quitStr = s->_segMan->getString(argv[0]); - debug("Setting quit string to '%s'", quitStr.c_str()); + //debug("Setting quit string to '%s'", quitStr.c_str()); return s->r_acc; } @@ -578,7 +584,8 @@ reg_t kStrSplit(EngineState *s, int argc, reg_t *argv) { // Make sure target buffer is large enough SegmentRef buf_r = s->_segMan->dereference(argv[0]); if (!buf_r.isValid() || buf_r.maxSize < (int)str.size() + 1) { - warning("StrSplit: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(argv[0]), str.size() + 1, str.c_str()); + warning("StrSplit: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", + PRINT_REG(argv[0]), str.size() + 1, str.c_str()); return NULL_REG; } s->_segMan->strcpy(argv[0], str.c_str()); diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp index 07f8792471..18e60eb521 100644 --- a/engines/sci/engine/message.cpp +++ b/engines/sci/engine/message.cpp @@ -161,7 +161,7 @@ bool MessageState::getRecord(CursorStack &stack, bool recurse, MessageRecord &re reader = new MessageReaderV4(res->data, res->size); break; default: - warning("Message: unsupported resource version %d", version); + error("Message: unsupported resource version %d", version); return false; } @@ -259,7 +259,7 @@ void MessageState::popCursorStack() { if (!_cursorStackStack.empty()) _cursorStack = _cursorStackStack.pop(); else - warning("Message: attempt to pop from empty stack"); + error("Message: attempt to pop from empty stack"); } int MessageState::hexDigitToInt(char h) { @@ -330,7 +330,8 @@ bool MessageState::stringStage(Common::String &outstr, const Common::String &inS } // If we find a lowercase character or a digit, it's not a stage direction - if (((inStr[i] >= 'a') && (inStr[i] <= 'z')) || ((inStr[i] >= '0') && (inStr[i] <= '9'))) + // SCI32 seems to support having digits in stage directions + if (((inStr[i] >= 'a') && (inStr[i] <= 'z')) || ((inStr[i] >= '0') && (inStr[i] <= '9') && (getSciVersion() < SCI_VERSION_2))) return false; } diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 9bf23dedf5..0fe5f2088a 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -33,24 +33,18 @@ #include "sci/event.h" #include "sci/engine/features.h" +#include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/message.h" #include "sci/engine/savegame.h" +#include "sci/engine/selector.h" #include "sci/engine/vm_types.h" #include "sci/engine/script.h" // for SCI_OBJ_EXPORTS and SCI_OBJ_SYNONYMS -#include "sci/graphics/gui.h" #include "sci/graphics/ports.h" #include "sci/sound/audio.h" -#ifdef USE_OLD_MUSIC_FUNCTIONS -#include "sci/sound/iterator/core.h" -#include "sci/sound/iterator/iterator.h" -#else #include "sci/sound/music.h" -#endif -#ifdef ENABLE_SCI32 -#include "sci/graphics/gui32.h" -#endif +#include "gui/message.h" namespace Sci { @@ -62,47 +56,11 @@ namespace Sci { const uint32 INTMAPPER_MAGIC_KEY = 0xDEADBEEF; -#ifdef USE_OLD_MUSIC_FUNCTIONS -// from ksound.cpp: -SongIterator *build_iterator(ResourceManager *resMan, int song_nr, SongIteratorType type, songit_id_t id); -#endif - - #pragma mark - // TODO: Many of the following sync_*() methods should be turned into member funcs // of the classes they are syncing. -#ifdef USE_OLD_MUSIC_FUNCTIONS -static void sync_songlib(Common::Serializer &s, SongLibrary &obj); -#endif - -static void sync_reg_t(Common::Serializer &s, reg_t &obj) { - s.syncAsUint16LE(obj.segment); - s.syncAsUint16LE(obj.offset); -} - -#ifdef USE_OLD_MUSIC_FUNCTIONS -static void syncSong(Common::Serializer &s, Song &obj) { - s.syncAsSint32LE(obj._handle); - s.syncAsSint32LE(obj._resourceNum); - s.syncAsSint32LE(obj._priority); - s.syncAsSint32LE(obj._status); - s.syncAsSint32LE(obj._restoreBehavior); - s.syncAsSint32LE(obj._restoreTime); - s.syncAsSint32LE(obj._loops); - s.syncAsSint32LE(obj._hold); - - if (s.isLoading()) { - obj._it = 0; - obj._delay = 0; - obj._next = 0; - obj._nextPlaying = 0; - obj._nextStopping = 0; - } -} -#else - #define DEFROBNICATE_HANDLE(handle) (make_reg((handle >> 16) & 0xffff, handle & 0xffff)) void MusicEntry::saveLoadWithSerializer(Common::Serializer &s) { @@ -132,7 +90,7 @@ void MusicEntry::saveLoadWithSerializer(Common::Serializer &s) { fadeTickerStep = 0; } else { // A bit more optimized saving - sync_reg_t(s, soundObj); + soundObj.saveLoadWithSerializer(s); s.syncAsSint16LE(resourceId); s.syncAsSint16LE(dataInc); s.syncAsSint16LE(ticker); @@ -156,7 +114,6 @@ void MusicEntry::saveLoadWithSerializer(Common::Serializer &s) { pStreamAud = 0; } } -#endif // Experimental hack: Use syncWithSerializer to sync. By default, this assume // the object to be synced is a subclass of Serializable and thus tries to invoke @@ -217,31 +174,18 @@ void syncArray(Common::Serializer &s, Common::Array<T> &arr) { template <> void syncWithSerializer(Common::Serializer &s, reg_t &obj) { - sync_reg_t(s, obj); + obj.saveLoadWithSerializer(s); } void SegManager::saveLoadWithSerializer(Common::Serializer &s) { - s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be reserved_id - s.skip(4, VER(9), VER(18)); // OBSOLETE: Used to be _exportsAreWide - s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be gc_mark_bits + if (s.isLoading()) + resetSegMan(); + + s.skip(4, VER(12), VER(18)); // OBSOLETE: Used to be _exportsAreWide if (s.isLoading()) { // Reset _scriptSegMap, to be restored below _scriptSegMap.clear(); - - if (s.getVersion() <= 9) { - // OBSOLETE: Skip over the old id_seg_map when loading (we now - // regenerate the equivalent data, in _scriptSegMap, from scratch). - - s.skip(4); // base_value - while (true) { - uint32 key = 0; - s.syncAsSint32LE(key); - if (key == INTMAPPER_MAGIC_KEY) - break; - s.skip(4); // idx - } - } } @@ -257,57 +201,38 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { // If we were saving and mobj == 0, or if we are loading and this is an // entry marked as empty -> skip to next - if (type == SEG_TYPE_INVALID) { + if (type == SEG_TYPE_INVALID) continue; - } - - s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be _segManagerId // Don't save or load HunkTable segments - if (type == SEG_TYPE_HUNK) { + if (type == SEG_TYPE_HUNK) continue; - } - - // Handle the OBSOLETE type SEG_TYPE_STRING_FRAG -- just ignore it - if (s.isLoading() && type == SEG_TYPE_STRING_FRAG) { - continue; - } - - if (s.isLoading()) { + if (s.isLoading()) mobj = SegmentObj::createSegmentObj(type); - } + assert(mobj); // Let the object sync custom data mobj->saveLoadWithSerializer(s); // If we are loading a script, hook it up in the script->segment map. - if (s.isLoading() && type == SEG_TYPE_SCRIPT) { - _scriptSegMap[((Script *)mobj)->_nr] = i; - } + if (s.isLoading() && type == SEG_TYPE_SCRIPT) + _scriptSegMap[((Script *)mobj)->getScriptNumber()] = i; } - s.syncAsSint32LE(Clones_seg_id); - s.syncAsSint32LE(Lists_seg_id); - s.syncAsSint32LE(Nodes_seg_id); -} - -static void sync_SegManagerPtr(Common::Serializer &s, SegManager *&obj) { - s.skip(1, VER(9), VER(9)); // obsolete: used to be a flag indicating if we got sci11 or not - - if (s.isLoading()) - obj->resetSegMan(); + s.syncAsSint32LE(_clonesSegId); + s.syncAsSint32LE(_listsSegId); + s.syncAsSint32LE(_nodesSegId); - obj->saveLoadWithSerializer(s); + syncArray<Class>(s, _classTable); } - template <> void syncWithSerializer(Common::Serializer &s, Class &obj) { s.syncAsSint32LE(obj.script); - sync_reg_t(s, obj.reg); + obj.reg.saveLoadWithSerializer(s); } static void sync_SavegameMetadata(Common::Serializer &s, SavegameMetadata &obj) { @@ -318,17 +243,20 @@ static void sync_SavegameMetadata(Common::Serializer &s, SavegameMetadata &obj) s.syncVersion(CURRENT_SAVEGAME_VERSION); obj.savegame_version = s.getVersion(); s.syncString(obj.game_version); - s.skip(4, VER(9), VER(9)); // obsolete: used to be game version s.syncAsSint32LE(obj.savegame_date); s.syncAsSint32LE(obj.savegame_time); + if (s.getVersion() < 22) { + obj.game_object_offset = 0; + obj.script0_size = 0; + } else { + s.syncAsUint16LE(obj.game_object_offset); + s.syncAsUint16LE(obj.script0_size); + } } void EngineState::saveLoadWithSerializer(Common::Serializer &s) { - s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be savegame_version - Common::String tmp; - s.syncString(tmp); // OBSOLETE: Used to be game_version - s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be version + s.syncString(tmp, VER(12), VER(23)); // OBSOLETE: Used to be game_version // OBSOLETE: Saved menus. Skip all of the saved data if (s.getVersion() < 14) { @@ -347,7 +275,6 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { for (int j = 0; j < menuLength; j++) { s.skip(4, VER(12), VER(12)); // OBSOLETE: Used to be _type s.syncString(tmp); // OBSOLETE: Used to be _keytext - s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be keytext_size s.skip(4, VER(12), VER(12)); // OBSOLETE: Used to be _flags s.skip(64, VER(12), VER(12)); // OBSOLETE: Used to be MENU_SAID_SPEC_SIZE @@ -362,16 +289,14 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { s.skip(4, VER(12), VER(12)); // obsolete: used to be status_bar_foreground s.skip(4, VER(12), VER(12)); // obsolete: used to be status_bar_background - if (s.getVersion() >= 13 && g_sci->_gui) { - // Save/Load picPort as well (cause sierra sci also does this) + if (s.getVersion() >= 13 && getSciVersion() <= SCI_VERSION_1_1) { + // Save/Load picPort as well for SCI0-SCI1.1. Necessary for Castle of Dr. Brain, + // as the picPort has been changed when loading during the intro int16 picPortTop, picPortLeft; Common::Rect picPortRect; - if (s.isSaving()) { - // FIXME: _gfxPorts is 0 when using SCI32 code - assert(g_sci->_gfxPorts); + if (s.isSaving()) picPortRect = g_sci->_gfxPorts->kernelGetPicWindow(picPortTop, picPortLeft); - } s.syncAsSint16LE(picPortRect.top); s.syncAsSint16LE(picPortRect.left); @@ -379,17 +304,14 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { s.syncAsSint16LE(picPortRect.right); s.syncAsSint16LE(picPortTop); s.syncAsSint16LE(picPortLeft); - } - sync_SegManagerPtr(s, _segMan); + if (s.isLoading()) + g_sci->_gfxPorts->kernelSetPicWindow(picPortRect, picPortTop, picPortLeft, false); + } - syncArray<Class>(s, _segMan->_classTable); + _segMan->saveLoadWithSerializer(s); -#ifdef USE_OLD_MUSIC_FUNCTIONS - sync_songlib(s, _sound._songlib); -#else - _soundCmd->syncPlayList(s); -#endif + g_sci->_soundCmd->syncPlayList(s); } void LocalVariables::saveLoadWithSerializer(Common::Serializer &s) { @@ -400,8 +322,8 @@ void LocalVariables::saveLoadWithSerializer(Common::Serializer &s) { void Object::saveLoadWithSerializer(Common::Serializer &s) { s.syncAsSint32LE(_flags); - sync_reg_t(s, _pos); - s.skip(4, VER(9), VER(12)); // OBSOLETE: Used to be variable_names_nr + _pos.saveLoadWithSerializer(s); + s.skip(4, VER(12), VER(12)); // OBSOLETE: Used to be variable_names_nr s.syncAsSint32LE(_methodCount); // that's actually a uint16 syncArray<reg_t>(s, _variables); @@ -418,18 +340,18 @@ template <> void syncWithSerializer(Common::Serializer &s, Table<List>::Entry &obj) { s.syncAsSint32LE(obj.next_free); - sync_reg_t(s, obj.first); - sync_reg_t(s, obj.last); + obj.first.saveLoadWithSerializer(s); + obj.last.saveLoadWithSerializer(s); } template <> void syncWithSerializer(Common::Serializer &s, Table<Node>::Entry &obj) { s.syncAsSint32LE(obj.next_free); - sync_reg_t(s, obj.pred); - sync_reg_t(s, obj.succ); - sync_reg_t(s, obj.key); - sync_reg_t(s, obj.value); + obj.pred.saveLoadWithSerializer(s); + obj.succ.saveLoadWithSerializer(s); + obj.key.saveLoadWithSerializer(s); + obj.value.saveLoadWithSerializer(s); } #ifdef ENABLE_SCI32 @@ -463,7 +385,7 @@ void syncWithSerializer(Common::Serializer &s, Table<SciArray<reg_t> >::Entry &o if (s.isSaving()) value = obj.getValue(i); - sync_reg_t(s, value); + value.saveLoadWithSerializer(s); if (s.isLoading()) obj.setValue(i, value); @@ -524,25 +446,15 @@ void HunkTable::saveLoadWithSerializer(Common::Serializer &s) { void Script::saveLoadWithSerializer(Common::Serializer &s) { s.syncAsSint32LE(_nr); - s.syncAsUint32LE(_bufSize); - s.syncAsUint32LE(_scriptSize); - s.syncAsUint32LE(_heapSize); - - if (s.getVersion() <= 10) { - assert((s.isLoading())); - // OBSOLETE: Skip over the old _objIndices data when loading - s.skip(4); // base_value - while (true) { - uint32 key = 0; - s.syncAsSint32LE(key); - if (key == INTMAPPER_MAGIC_KEY) - break; - s.skip(4); // idx - } - } - s.skip(4, VER(9), VER(19)); // OBSOLETE: Used to be _numExports - s.skip(4, VER(9), VER(19)); // OBSOLETE: Used to be _numSynonyms + if (s.isLoading()) + init(_nr, g_sci->getResMan()); + s.skip(4, VER(12), VER(22)); // OBSOLETE: Used to be _bufSize + s.skip(4, VER(12), VER(22)); // OBSOLETE: Used to be _scriptSize + s.skip(4, VER(12), VER(22)); // OBSOLETE: Used to be _heapSize + + s.skip(4, VER(12), VER(19)); // OBSOLETE: Used to be _numExports + s.skip(4, VER(12), VER(19)); // OBSOLETE: Used to be _numSynonyms s.syncAsSint32LE(_lockers); // Sync _objects. This is a hashmap, and we use the following on disk format: @@ -570,7 +482,7 @@ void Script::saveLoadWithSerializer(Common::Serializer &s) { } } - s.syncAsSint32LE(_localsOffset); + s.skip(4, VER(12), VER(20)); // OBSOLETE: Used to be _localsOffset s.syncAsSint32LE(_localsSegment); s.syncAsSint32LE(_markedAsDeleted); @@ -622,30 +534,6 @@ void DataStack::saveLoadWithSerializer(Common::Serializer &s) { #pragma mark - -#ifdef USE_OLD_MUSIC_FUNCTIONS -static void sync_songlib(Common::Serializer &s, SongLibrary &obj) { - int songcount = 0; - if (s.isSaving()) - songcount = obj.countSongs(); - s.syncAsUint32LE(songcount); - - if (s.isLoading()) { - obj._lib = 0; - while (songcount--) { - Song *newsong = new Song; - syncSong(s, *newsong); - obj.addSong(newsong); - } - } else { - Song *seeker = obj._lib; - while (seeker) { - seeker->_restoreTime = seeker->_it->getTimepos(); - syncSong(s, *seeker); - seeker = seeker->_next; - } - } -} -#else void SciMusic::saveLoadWithSerializer(Common::Serializer &s) { // Sync song lib data. When loading, the actual song lib will be initialized // afterwards in gamestate_restore() @@ -694,7 +582,35 @@ void SciMusic::saveLoadWithSerializer(Common::Serializer &s) { } } } -#endif + +void SoundCommandParser::syncPlayList(Common::Serializer &s) { + _music->saveLoadWithSerializer(s); +} + +void SoundCommandParser::reconstructPlayList(int savegame_version) { + Common::StackLock lock(_music->_mutex); + + const MusicList::iterator end = _music->getPlayListEnd(); + for (MusicList::iterator i = _music->getPlayListStart(); i != end; ++i) { + if ((*i)->resourceId && _resMan->testResource(ResourceId(kResourceTypeSound, (*i)->resourceId))) { + (*i)->soundRes = new SoundResource((*i)->resourceId, _resMan, _soundVersion); + _music->soundInitSnd(*i); + } else { + (*i)->soundRes = 0; + } + if ((*i)->status == kSoundPlaying) { + if (savegame_version < 14) { + (*i)->dataInc = readSelectorValue(_segMan, (*i)->soundObj, SELECTOR(dataInc)); + (*i)->signal = readSelectorValue(_segMan, (*i)->soundObj, SELECTOR(signal)); + + if (_soundVersion >= SCI_VERSION_1_LATE) + (*i)->volume = readSelectorValue(_segMan, (*i)->soundObj, SELECTOR(vol)); + } + + processPlaySound((*i)->soundObj); + } + } +} #ifdef ENABLE_SCI32 void ArrayTable::saveLoadWithSerializer(Common::Serializer &ser) { @@ -712,43 +628,13 @@ void StringTable::saveLoadWithSerializer(Common::Serializer &ser) { } #endif -#pragma mark - - - -int gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename, const char *version) { - TimeDate curTime; - g_system->getTimeAndDate(curTime); - - SavegameMetadata meta; - meta.savegame_version = CURRENT_SAVEGAME_VERSION; - meta.savegame_name = savename; - meta.game_version = version; - meta.savegame_date = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF); - meta.savegame_time = ((curTime.tm_hour & 0xFF) << 16) | (((curTime.tm_min) & 0xFF) << 8) | ((curTime.tm_sec) & 0xFF); - - if (s->execution_stack_base) { - warning("Cannot save from below kernel function"); - return 1; - } - - Common::Serializer ser(0, fh); - sync_SavegameMetadata(ser, meta); - Graphics::saveThumbnail(*fh); - s->saveLoadWithSerializer(ser); // FIXME: Error handling? - - return 0; +void SegManager::reconstructStack(EngineState *s) { + DataStack *stack = (DataStack *)(_heap[findSegmentByType(SEG_TYPE_STACK)]); + s->stack_base = stack->_entries; + s->stack_top = s->stack_base + stack->_capacity; } -// TODO: This should probably be turned into an EngineState or DataStack method. -static void reconstruct_stack(EngineState *retval) { - SegmentId stack_seg = retval->_segMan->findSegmentByType(SEG_TYPE_STACK); - DataStack *stack = (DataStack *)(retval->_segMan->_heap[stack_seg]); - - retval->stack_base = stack->_entries; - retval->stack_top = stack->_entries + stack->_capacity; -} - -// TODO: Move thie function to a more appropriate place, such as vm.cpp or script.cpp +// TODO: Move this function to a more appropriate place, such as vm.cpp or script.cpp void SegManager::reconstructScripts(EngineState *s) { uint i; @@ -761,7 +647,7 @@ void SegManager::reconstructScripts(EngineState *s) { scr->_localsBlock = (scr->_localsSegment == 0) ? NULL : (LocalVariables *)(_heap[scr->_localsSegment]); for (ObjMap::iterator it = scr->_objects.begin(); it != scr->_objects.end(); ++it) - it->_value._baseObj = scr->_buf + it->_value.getPos().offset; + it->_value._baseObj = scr->getBuf(it->_value.getPos().offset); } for (i = 0; i < _heap.size(); i++) { @@ -776,6 +662,8 @@ void SegManager::reconstructScripts(EngineState *s) { if (getSciVersion() < SCI_VERSION_1_1) { if (!obj->initBaseObject(this, addr, false)) { + // TODO/FIXME: This should not be happening at all. It might indicate a possible issue + // with the garbage collector. It happens for example in LSL5 (German, perhaps English too). warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); scr->scriptObjRemove(addr); } @@ -784,47 +672,70 @@ void SegManager::reconstructScripts(EngineState *s) { } } -#ifdef USE_OLD_MUSIC_FUNCTIONS -static void reconstruct_sounds(EngineState *s) { - Song *seeker; - SongIteratorType it_type; +void SegManager::reconstructClones() { + for (uint i = 0; i < _heap.size(); i++) { + SegmentObj *mobj = _heap[i]; + if (mobj && mobj->getType() == SEG_TYPE_CLONES) { + CloneTable *ct = (CloneTable *)mobj; + + for (uint j = 0; j < ct->_table.size(); j++) { + // Check if the clone entry is used + uint entryNum = (uint)ct->first_free; + bool isUsed = true; + while (entryNum != ((uint) CloneTable::HEAPENTRY_INVALID)) { + if (entryNum == j) { + isUsed = false; + break; + } + entryNum = ct->_table[entryNum].next_free; + } + + if (!isUsed) + continue; - if (getSciVersion() > SCI_VERSION_01) - it_type = SCI_SONG_ITERATOR_TYPE_SCI1; - else - it_type = SCI_SONG_ITERATOR_TYPE_SCI0; + CloneTable::Entry &seeker = ct->_table[j]; + const Object *baseObj = getObject(seeker.getSpeciesSelector()); + seeker.cloneFromObject(baseObj); + if (!baseObj) + error("Clone entry without a base class: %d", j); + } // end for + } // end if + } // end for +} - seeker = s->_sound._songlib._lib; - while (seeker) { - SongIterator *base, *ff = 0; - int oldstatus; - SongIterator::Message msg; +#pragma mark - - base = ff = build_iterator(g_sci->getResMan(), seeker->_resourceNum, it_type, seeker->_handle); - if (seeker->_restoreBehavior == RESTORE_BEHAVIOR_CONTINUE) - ff = new_fast_forward_iterator(base, seeker->_restoreTime); - ff->init(); - msg = SongIterator::Message(seeker->_handle, SIMSG_SET_LOOPS(seeker->_loops)); - songit_handle_message(&ff, msg); - msg = SongIterator::Message(seeker->_handle, SIMSG_SET_HOLD(seeker->_hold)); - songit_handle_message(&ff, msg); +bool gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename, const char *version) { + TimeDate curTime; + g_system->getTimeAndDate(curTime); - oldstatus = seeker->_status; - seeker->_status = SOUND_STATUS_STOPPED; - seeker->_it = ff; - s->_sound.sfx_song_set_status(seeker->_handle, oldstatus); - seeker = seeker->_next; + SavegameMetadata meta; + meta.savegame_version = CURRENT_SAVEGAME_VERSION; + meta.savegame_name = savename; + meta.game_version = version; + meta.savegame_date = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF); + meta.savegame_time = ((curTime.tm_hour & 0xFF) << 16) | (((curTime.tm_min) & 0xFF) << 8) | ((curTime.tm_sec) & 0xFF); + + Resource *script0 = g_sci->getResMan()->findResource(ResourceId(kResourceTypeScript, 0), false); + meta.script0_size = script0->size; + meta.game_object_offset = g_sci->getGameObject().offset; + + if (s->executionStackBase) { + warning("Cannot save from below kernel function"); + return false; } + + Common::Serializer ser(0, fh); + sync_SavegameMetadata(ser, meta); + Graphics::saveThumbnail(*fh); + s->saveLoadWithSerializer(ser); // FIXME: Error handling? + + return true; } -#endif void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { -#ifdef USE_OLD_MUSIC_FUNCTIONS - SongLibrary temp; -#endif - SavegameMetadata meta; Common::Serializer ser(fh, 0); @@ -837,85 +748,62 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { if ((meta.savegame_version < MINIMUM_SAVEGAME_VERSION) || (meta.savegame_version > CURRENT_SAVEGAME_VERSION)) { + /* if (meta.savegame_version < MINIMUM_SAVEGAME_VERSION) - warning("Old savegame version detected- can't load"); + warning("Old savegame version detected, unable to load it"); else - warning("Savegame version is %d- maximum supported is %0d", meta.savegame_version, CURRENT_SAVEGAME_VERSION); + warning("Savegame version is %d, maximum supported is %0d", meta.savegame_version, CURRENT_SAVEGAME_VERSION); + */ + + GUI::MessageDialog dialog("The format of this saved game is obsolete, unable to load it", "OK"); + dialog.runModal(); s->r_acc = make_reg(0, 1); // signal failure return; } - if (meta.savegame_version >= 12) { - // We don't need the thumbnail here, so just read it and discard it - Graphics::Surface *thumbnail = new Graphics::Surface(); - assert(thumbnail); - Graphics::loadThumbnail(*fh, *thumbnail); - delete thumbnail; - thumbnail = 0; + if (meta.game_object_offset > 0 && meta.script0_size > 0) { + Resource *script0 = g_sci->getResMan()->findResource(ResourceId(kResourceTypeScript, 0), false); + if (script0->size != meta.script0_size || g_sci->getGameObject().offset != meta.game_object_offset) { + //warning("This saved game was created with a different version of the game, unable to load it"); + + GUI::MessageDialog dialog("This saved game was created with a different version of the game, unable to load it", "OK"); + dialog.runModal(); + + s->r_acc = make_reg(0, 1); // signal failure + return; + } } + // We don't need the thumbnail here, so just read it and discard it + Graphics::Surface *thumbnail = new Graphics::Surface(); + assert(thumbnail); + Graphics::loadThumbnail(*fh, *thumbnail); + delete thumbnail; + thumbnail = 0; + s->reset(true); s->saveLoadWithSerializer(ser); // FIXME: Error handling? -#ifdef USE_OLD_MUSIC_FUNCTIONS - s->_sound.sfx_exit(); -#endif - - // Set exec stack base to zero - s->execution_stack_base = 0; - // Now copy all current state information -#ifdef USE_OLD_MUSIC_FUNCTIONS - temp = s->_sound._songlib; - s->_sound.sfx_init(g_sci->getResMan(), s->sfx_init_flags, g_sci->_features->detectDoSoundType()); - s->sfx_init_flags = s->sfx_init_flags; - s->_sound._songlib.freeSounds(); - s->_sound._songlib = temp; - s->_soundCmd->updateSfxState(&retval->_sound); -#endif - - reconstruct_stack(s); + s->_segMan->reconstructStack(s); s->_segMan->reconstructScripts(s); s->_segMan->reconstructClones(); - s->_gameObj = s->_gameObj; - s->script_000 = s->_segMan->getScript(s->_segMan->getScriptSegment(0, SCRIPT_GET_DONT_LOAD)); - s->gc_countdown = GC_INTERVAL - 1; + s->initGlobals(); + s->gcCountDown = GC_INTERVAL - 1; // Time state: - s->last_wait_time = g_system->getMillis(); - s->game_start_time = g_system->getMillis(); - - s->restoring = false; - -#ifdef USE_OLD_MUSIC_FUNCTIONS - s->_sound._it = NULL; - s->_sound._flags = s->_sound._flags; - s->_sound._song = NULL; - s->_sound._suspended = s->_sound._suspended; - reconstruct_sounds(s); -#else - s->_soundCmd->reconstructPlayList(meta.savegame_version); -#endif + s->lastWaitTime = g_system->getMillis(); + s->gameStartTime = g_system->getMillis(); + s->_screenUpdateTime = g_system->getMillis(); + + g_sci->_soundCmd->reconstructPlayList(meta.savegame_version); // Message state: s->_msgState = new MessageState(s->_segMan); -#ifdef ENABLE_SCI32 - if (g_sci->_gui32) { - g_sci->_gui32->init(); - } else { -#endif - g_sci->_gui->resetEngineState(s); - g_sci->_gui->init(g_sci->_features->usesOldGfxFunctions()); -#ifdef ENABLE_SCI32 - } -#endif - - - s->restoring = true; - s->script_abort_flag = 2; // Abort current game with replay + s->abortScriptProcessing = kAbortLoadGame; s->shrinkStackToBase(); } diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h index 7be05381da..9a882f2bf7 100644 --- a/engines/sci/engine/savegame.h +++ b/engines/sci/engine/savegame.h @@ -36,8 +36,8 @@ namespace Sci { struct EngineState; enum { - CURRENT_SAVEGAME_VERSION = 20, - MINIMUM_SAVEGAME_VERSION = 9 + CURRENT_SAVEGAME_VERSION = 23, + MINIMUM_SAVEGAME_VERSION = 12 }; // Savegame metadata @@ -47,6 +47,8 @@ struct SavegameMetadata { Common::String game_version; int savegame_date; int savegame_time; + uint16 game_object_offset; + uint16 script0_size; }; @@ -57,7 +59,7 @@ struct SavegameMetadata { * @param savename The description of the savegame * @return 0 on success, 1 otherwise */ -int gamestate_save(EngineState *s, Common::WriteStream *save, const char *savename, const char *version); +bool gamestate_save(EngineState *s, Common::WriteStream *save, const char *savename, const char *version); /** * Restores a game state from a directory. diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 1f32e50b67..a293f81d2f 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -35,431 +35,553 @@ namespace Sci { -#define END Script_None - -opcode_format g_opcode_formats[128][4] = { - /*00*/ - {Script_None}, {Script_None}, {Script_None}, {Script_None}, - /*04*/ - {Script_None}, {Script_None}, {Script_None}, {Script_None}, - /*08*/ - {Script_None}, {Script_None}, {Script_None}, {Script_None}, - /*0C*/ - {Script_None}, {Script_None}, {Script_None}, {Script_None}, - /*10*/ - {Script_None}, {Script_None}, {Script_None}, {Script_None}, - /*14*/ - {Script_None}, {Script_None}, {Script_None}, {Script_SRelative, END}, - /*18*/ - {Script_SRelative, END}, {Script_SRelative, END}, {Script_SVariable, END}, {Script_None}, - /*1C*/ - {Script_SVariable, END}, {Script_None}, {Script_None}, {Script_Variable, END}, - /*20*/ - {Script_SRelative, Script_Byte, END}, {Script_Variable, Script_Byte, END}, {Script_Variable, Script_Byte, END}, {Script_Variable, Script_SVariable, Script_Byte, END}, - /*24 (24=ret)*/ - {Script_End}, {Script_Byte, END}, {Script_Invalid}, {Script_Invalid}, - /*28*/ - {Script_Variable, END}, {Script_Invalid}, {Script_Byte, END}, {Script_Variable, Script_Byte, END}, - /*2C*/ - {Script_SVariable, END}, {Script_SVariable, Script_Variable, END}, {Script_None}, {Script_Invalid}, - /*30*/ - {Script_None}, {Script_Property, END}, {Script_Property, END}, {Script_Property, END}, - /*34*/ - {Script_Property, END}, {Script_Property, END}, {Script_Property, END}, {Script_Property, END}, - /*38*/ - {Script_Property, END}, {Script_SRelative, END}, {Script_SRelative, END}, {Script_None}, - /*3C*/ - {Script_None}, {Script_None}, {Script_None}, {Script_Word}, - /*40-4F*/ - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - /*50-5F*/ - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - /*60-6F*/ - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - /*70-7F*/ - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END} -}; -#undef END - -// TODO: script_adjust_opcode_formats should probably be part of the -// constructor (?) of a VirtualMachine or a ScriptManager class. -void script_adjust_opcode_formats(EngineState *s) { - // TODO: Check that this is correct - if (g_sci->_features->detectLofsType() != SCI_VERSION_0_EARLY) { - g_opcode_formats[op_lofsa][0] = Script_Offset; - g_opcode_formats[op_lofss][0] = Script_Offset; - } +Script::Script() : SegmentObj(SEG_TYPE_SCRIPT) { + _nr = 0; + _buf = NULL; + _bufSize = 0; + _scriptSize = 0; + _heapSize = 0; + + _synonyms = NULL; + _heapStart = NULL; + _exportTable = NULL; + + _localsOffset = 0; + _localsSegment = 0; + _localsBlock = NULL; + _localsCount = 0; + + _markedAsDeleted = false; +} + +Script::~Script() { + freeScript(); +} + +void Script::freeScript() { + free(_buf); + _buf = NULL; + _bufSize = 0; -#ifdef ENABLE_SCI32 - // In SCI32, some arguments are now words instead of bytes - if (getSciVersion() >= SCI_VERSION_2) { - g_opcode_formats[op_calle][2] = Script_Word; - g_opcode_formats[op_callk][1] = Script_Word; - g_opcode_formats[op_super][1] = Script_Word; - g_opcode_formats[op_send][0] = Script_Word; - g_opcode_formats[op_self][0] = Script_Word; - g_opcode_formats[op_call][1] = Script_Word; - g_opcode_formats[op_callb][1] = Script_Word; + _objects.clear(); +} + +void Script::init(int script_nr, ResourceManager *resMan) { + Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0); + + _localsOffset = 0; + _localsBlock = NULL; + _localsCount = 0; + + _markedAsDeleted = false; + + _nr = script_nr; + _buf = 0; + _heapStart = 0; + + _scriptSize = script->size; + _bufSize = script->size; + _heapSize = 0; + + _lockers = 1; + + if (getSciVersion() == SCI_VERSION_0_EARLY) { + _bufSize += READ_LE_UINT16(script->data) * 2; + } else if (getSciVersion() >= SCI_VERSION_1_1) { + // In SCI11, the heap was in a separate space from the script. We append + // it to the end of the script, and adjust addressing accordingly. + // However, since we address the heap with a 16-bit pointer, the + // combined size of the stack and the heap must be 64KB. So far this has + // worked for SCI11, SCI2 and SCI21 games. SCI3 games use a different + // script format, and theoretically they can exceed the 64KB boundary + // using relocation. + Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, script_nr), 0); + _bufSize += heap->size; + _heapSize = heap->size; + + // Ensure that the start of the heap resource can be word-aligned. + if (script->size & 2) { + _bufSize++; + _scriptSize++; + } + + // As mentioned above, the script and the heap together should not exceed 64KB + if (script->size + heap->size > 65535) + error("Script and heap sizes combined exceed 64K. This means a fundamental " + "design bug was made regarding SCI1.1 and newer games.\n" + "Please report this error to the ScummVM team"); } -#endif } -void SegManager::createClassTable() { - Resource *vocab996 = _resMan->findResource(ResourceId(kResourceTypeVocab, 996), 1); +void Script::load(ResourceManager *resMan) { + Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, _nr), 0); + assert(script != 0); - if (!vocab996) - error("SegManager: failed to open vocab 996"); + _buf = (byte *)malloc(_bufSize); + assert(_buf); - int totalClasses = vocab996->size >> 2; - _classTable.resize(totalClasses); + assert(_bufSize >= script->size); + memcpy(_buf, script->data, script->size); + + if (getSciVersion() >= SCI_VERSION_1_1) { + Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, _nr), 0); + assert(heap != 0); - for (uint16 classNr = 0; classNr < totalClasses; classNr++) { - uint16 scriptNr = READ_SCI11ENDIAN_UINT16(vocab996->data + classNr * 4 + 2); + _heapStart = _buf + _scriptSize; - _classTable[classNr].reg = NULL_REG; - _classTable[classNr].script = scriptNr; + assert(_bufSize - _scriptSize <= heap->size); + memcpy(_heapStart, heap->data, heap->size); } - _resMan->unlockResource(vocab996); -} + _exportTable = 0; + _numExports = 0; + _synonyms = 0; + _numSynonyms = 0; + + if (getSciVersion() >= SCI_VERSION_1_1) { + if (READ_LE_UINT16(_buf + 1 + 5) > 0) { // does the script have an export table? + _exportTable = (const uint16 *)(_buf + 1 + 5 + 2); + _numExports = READ_SCI11ENDIAN_UINT16(_exportTable - 1); + } + _localsOffset = _scriptSize + 4; + _localsCount = READ_SCI11ENDIAN_UINT16(_buf + _localsOffset - 2); + } else { + _exportTable = (const uint16 *)findBlock(SCI_OBJ_EXPORTS); + if (_exportTable) { + _numExports = READ_SCI11ENDIAN_UINT16(_exportTable + 1); + _exportTable += 3; // skip header plus 2 bytes (_exportTable is a uint16 pointer) + } + _synonyms = findBlock(SCI_OBJ_SYNONYMS); + if (_synonyms) { + _numSynonyms = READ_SCI11ENDIAN_UINT16(_synonyms + 2) / 4; + _synonyms += 4; // skip header + } + const byte* localsBlock = findBlock(SCI_OBJ_LOCALVARS); + if (localsBlock) { + _localsOffset = localsBlock - _buf + 4; + _localsCount = (READ_LE_UINT16(_buf + _localsOffset - 2) - 4) >> 1; // half block size + } + } -reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, reg_t caller) { - if (classnr == 0xffff) - return NULL_REG; + if (getSciVersion() > SCI_VERSION_0_EARLY) { + // Does the script actually have locals? If not, set the locals offset to 0 + if (!_localsCount) + _localsOffset = 0; - if (classnr < 0 || (int)_classTable.size() <= classnr || _classTable[classnr].script < 0) { - error("[VM] Attempt to dereference class %x, which doesn't exist (max %x)", classnr, _classTable.size()); - return NULL_REG; + if (_localsOffset + _localsCount * 2 + 1 >= (int)_bufSize) { + error("Locals extend beyond end of script: offset %04x, count %d vs size %d", _localsOffset, _localsCount, _bufSize); + _localsCount = (_bufSize - _localsOffset) >> 1; + } } else { - Class *the_class = &_classTable[classnr]; - if (!the_class->reg.segment) { - getScriptSegment(the_class->script, lock); + // Old script block. There won't be a localvar block in this case. + // Instead, the script starts with a 16 bit int specifying the + // number of locals we need; these are then allocated and zeroed. + _localsCount = READ_LE_UINT16(_buf); + _localsOffset = -_localsCount * 2; // Make sure it's invalid + } +} - if (!the_class->reg.segment) { - error("[VM] Trying to instantiate class %x by instantiating script 0x%x (%03d) failed;", classnr, the_class->script, the_class->script); - return NULL_REG; - } - } else - if (caller.segment != the_class->reg.segment) - getScript(the_class->reg.segment)->incrementLockers(); +Object *Script::getObject(uint16 offset) { + if (_objects.contains(offset)) + return &_objects[offset]; + else + return 0; +} - return the_class->reg; - } +const Object *Script::getObject(uint16 offset) const { + if (_objects.contains(offset)) + return &_objects[offset]; + else + return 0; } -void SegManager::scriptInitialiseLocalsZero(SegmentId seg, int count) { - Script *scr = getScript(seg); +Object *Script::scriptObjInit(reg_t obj_pos, bool fullObjectInit) { + if (getSciVersion() < SCI_VERSION_1_1 && fullObjectInit) + obj_pos.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET) - scr->_localsOffset = -count * 2; // Make sure it's invalid + VERIFY(obj_pos.offset < _bufSize, "Attempt to initialize object beyond end of script\n"); - LocalVariables *locals = allocLocalsSegment(scr, count); - if (locals) { - for (int i = 0; i < count; i++) - locals->_locals[i] = NULL_REG; - } + VERIFY(obj_pos.offset + kOffsetFunctionArea < (int)_bufSize, "Function area pointer stored beyond end of script\n"); + + // Get the object at the specified position and init it. This will + // automatically "allocate" space for it in the _objects map if necessary. + Object *obj = &_objects[obj_pos.offset]; + obj->init(_buf, obj_pos, fullObjectInit); + + return obj; } -void SegManager::scriptInitialiseLocals(reg_t location) { - Script *scr = getScript(location.segment); - unsigned int count; +void Script::scriptObjRemove(reg_t obj_pos) { + if (getSciVersion() < SCI_VERSION_1_1) + obj_pos.offset += 8; - VERIFY(location.offset + 1 < (uint16)scr->getBufSize(), "Locals beyond end of script\n"); + _objects.erase(obj_pos.toUint16()); +} - if (getSciVersion() >= SCI_VERSION_1_1) - count = READ_SCI11ENDIAN_UINT16(scr->_buf + location.offset - 2); - else - count = (READ_LE_UINT16(scr->_buf + location.offset - 2) - 4) >> 1; - // half block size +// This helper function is used by Script::relocateLocal and Object::relocate +// Duplicate in segment.cpp and script.cpp +static bool relocateBlock(Common::Array<reg_t> &block, int block_location, SegmentId segment, int location, size_t scriptSize) { + int rel = location - block_location; - scr->_localsOffset = location.offset; + if (rel < 0) + return false; - if (!(location.offset + count * 2 + 1 < scr->getBufSize())) { - warning("Locals extend beyond end of script: offset %04x, count %x vs size %x", location.offset, count, (uint)scr->getBufSize()); - count = (scr->getBufSize() - location.offset) >> 1; - } + uint idx = rel >> 1; - LocalVariables *locals = allocLocalsSegment(scr, count); - if (locals) { - uint i; - const byte *base = (const byte *)(scr->_buf + location.offset); + if (idx >= block.size()) + return false; - for (i = 0; i < count; i++) - locals->_locals[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(base + i * 2)); + if (rel & 1) { + error("Attempt to relocate odd variable #%d.5e (relative to %04x)\n", idx, block_location); + return false; } + block[idx].segment = segment; // Perform relocation + if (getSciVersion() >= SCI_VERSION_1_1) + block[idx].offset += scriptSize; + + return true; } -void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { - Script *scr = getScript(seg); - const byte *seeker = scr->_heapStart + 4 + READ_SCI11ENDIAN_UINT16(scr->_heapStart + 2) * 2; +bool Script::relocateLocal(SegmentId segment, int location) { + if (_localsBlock) + return relocateBlock(_localsBlock->_locals, _localsOffset, segment, location, _scriptSize); + else + return false; +} - while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) { - if (READ_SCI11ENDIAN_UINT16(seeker + 14) & kInfoFlagClass) { // -info- selector - int classpos = seeker - scr->_buf; - int species = READ_SCI11ENDIAN_UINT16(seeker + 10); - - if (species < 0 || species >= (int)_classTable.size()) { - error("Invalid species %d(0x%x) not in interval [0,%d) while instantiating script %d", - species, species, _classTable.size(), scr->_nr); - return; - } +void Script::relocate(reg_t block) { + const byte *heap = _buf; + uint16 heapSize = (uint16)_bufSize; + uint16 heapOffset = 0; - _classTable[species].reg.segment = seg; - _classTable[species].reg.offset = classpos; - } - seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2; + if (getSciVersion() >= SCI_VERSION_1_1) { + heap = _heapStart; + heapSize = (uint16)_heapSize; + heapOffset = _scriptSize; } - seeker = scr->_heapStart + 4 + READ_SCI11ENDIAN_UINT16(scr->_heapStart + 2) * 2; - while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) { - reg_t reg = make_reg(seg, seeker - scr->_buf); - Object *obj = scr->scriptObjInit(reg); - - // Copy base from species class, as we need its selector IDs - obj->setSuperClassSelector( - getClassAddress(obj->getSuperClassSelector().offset, SCRIPT_GET_LOCK, NULL_REG)); - - // If object is instance, get -propDict- from class and set it for this object - // This is needed for ::isMemberOf() to work. - // Example testcase - room 381 of sq4cd - if isMemberOf() doesn't work, talk-clicks on the robot will act like - // clicking on ego - if (!obj->isClass()) { - reg_t classObject = obj->getSuperClassSelector(); - Object *classObj = getObject(classObject); - obj->setPropDictSelector(classObj->getPropDictSelector()); + VERIFY(block.offset < (uint16)heapSize && READ_SCI11ENDIAN_UINT16(heap + block.offset) * 2 + block.offset < (uint16)heapSize, + "Relocation block outside of script\n"); + + int count = READ_SCI11ENDIAN_UINT16(heap + block.offset); + int exportIndex = 0; + int pos = 0; + + for (int i = 0; i < count; i++) { + pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset; + // This occurs in SCI01/SCI1 games where usually one export value is + // zero. It seems that in this situation, we should skip the export and + // move to the next one, though the total count of valid exports remains + // the same + if (!pos) { + exportIndex++; + pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset; + if (!pos) + error("Script::relocate(): Consecutive zero exports found"); } - // Set the -classScript- selector to the script number. - // FIXME: As this selector is filled in at run-time, it is likely - // that it is supposed to hold a pointer. The Obj::isKindOf method - // uses this selector together with -propDict- to compare classes. - // For the purpose of Obj::isKindOf, using the script number appears - // to be sufficient. - obj->setClassScriptSelector(make_reg(0, scr->_nr)); + // In SCI0-SCI1, script local variables, objects and code are relocated. + // We only relocate locals and objects here, and ignore relocation of + // code blocks. In SCI1.1 and newer versions, only locals and objects + // are relocated. + if (!relocateLocal(block.segment, pos)) { + // Not a local? It's probably an object or code block. If it's an object, relocate it. + const ObjMap::iterator end = _objects.end(); + for (ObjMap::iterator it = _objects.begin(); it != end; ++it) + if (it->_value.relocate(block.segment, pos, _scriptSize)) + break; + } - seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2; + exportIndex++; } } -void script_instantiate_sci0(Script *scr, int segmentId, SegManager *segMan) { - int objType; - uint32 objLength = 0; - bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); - uint16 curOffset = oldScriptHeader ? 2 : 0; +void Script::incrementLockers() { + _lockers++; +} - if (oldScriptHeader) { - // Old script block - // There won't be a localvar block in this case - // Instead, the script starts with a 16 bit int specifying the - // number of locals we need; these are then allocated and zeroed. - int localsCount = READ_LE_UINT16(scr->_buf); - if (localsCount) - segMan->scriptInitialiseLocalsZero(segmentId, localsCount); - } +void Script::decrementLockers() { + if (_lockers > 0) + _lockers--; +} - // Now do a first pass through the script objects to find the - // local variable blocks +int Script::getLockers() const { + return _lockers; +} - do { - objType = scr->getHeap(curOffset); - if (!objType) - break; +void Script::setLockers(int lockers) { + _lockers = lockers; +} - objLength = scr->getHeap(curOffset + 2); - curOffset += 4; // skip header +uint16 Script::validateExportFunc(int pubfunct) { + bool exportsAreWide = (g_sci->_features->detectLofsType() == SCI_VERSION_1_MIDDLE); - switch (objType) { - case SCI_OBJ_LOCALVARS: - segMan->scriptInitialiseLocals(make_reg(segmentId, curOffset)); - break; - case SCI_OBJ_CLASS: { - int classpos = curOffset - SCRIPT_OBJECT_MAGIC_OFFSET; - int species = scr->getHeap(curOffset - SCRIPT_OBJECT_MAGIC_OFFSET + SCRIPT_SPECIES_OFFSET); - if (species < 0 || species >= (int)segMan->classTableSize()) { - if (species == (int)segMan->classTableSize()) { - // Happens in the LSL2 demo - warning("Applying workaround for an off-by-one invalid species access"); - segMan->resizeClassTable(segMan->classTableSize() + 1); - } else { - error("Invalid species %d(0x%x) not in interval " - "[0,%d) while instantiating script at segment %d\n", - species, species, segMan->classTableSize(), - segmentId); - return; - } - } + if (_numExports <= pubfunct) { + error("validateExportFunc(): pubfunct is invalid"); + return 0; + } - segMan->setClassOffset(species, make_reg(segmentId, classpos)); - // Set technical class position-- into the block allocated for it - } - break; + if (exportsAreWide) + pubfunct *= 2; + uint16 offset = READ_SCI11ENDIAN_UINT16(_exportTable + pubfunct); + VERIFY(offset < _bufSize, "invalid export function pointer"); - default: - break; - } + return offset; +} - curOffset += objLength - 4; - } while (objType != 0 && curOffset < scr->getScriptSize() - 2); +byte *Script::findBlock(int type) { + byte *buf = _buf; + bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); - // And now a second pass to adjust objects and class pointers, and the general pointers - objLength = 0; - curOffset = oldScriptHeader ? 2 : 0; + if (oldScriptHeader) + buf += 2; do { - objType = scr->getHeap(curOffset); - if (!objType) + int seekerType = READ_LE_UINT16(buf); + + if (seekerType == 0) break; + if (seekerType == type) + return buf; - objLength = scr->getHeap(curOffset + 2); - curOffset += 4; // skip header + int seekerSize = READ_LE_UINT16(buf + 2); + assert(seekerSize > 0); + buf += seekerSize; + } while (1); - reg_t addr = make_reg(segmentId, curOffset); + return NULL; +} - switch (objType) { - case SCI_OBJ_CODE: - scr->scriptAddCodeBlock(addr); - break; - case SCI_OBJ_OBJECT: - case SCI_OBJ_CLASS: { // object or class? - Object *obj = scr->scriptObjInit(addr); - obj->initSpecies(segMan, addr); +// memory operations - if (!obj->initBaseObject(segMan, addr)) { - warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); - scr->scriptObjRemove(addr); - } - } // if object or class - break; - default: - break; - } +void Script::mcpyInOut(int dst, const void *src, size_t n) { + if (_buf) { + assert(dst + n <= _bufSize); + memcpy(_buf + dst, src, n); + } +} + +bool Script::isValidOffset(uint16 offset) const { + return offset < _bufSize; +} + +SegmentRef Script::dereference(reg_t pointer) { + if (pointer.offset > _bufSize) { + error("Script::dereference(): Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)", + PRINT_REG(pointer), (uint)_bufSize); + return SegmentRef(); + } - curOffset += objLength - 4; - } while (objType != 0 && curOffset < scr->getScriptSize() - 2); + SegmentRef ret; + ret.isRaw = true; + ret.maxSize = _bufSize - pointer.offset; + ret.raw = _buf + pointer.offset; + return ret; } -int script_instantiate(ResourceManager *resMan, SegManager *segMan, int scriptNum) { - SegmentId segmentId = segMan->getScriptSegment(scriptNum); - Script *scr = segMan->getScriptIfLoaded(segmentId); - if (scr) { - if (!scr->isMarkedAsDeleted()) { - scr->incrementLockers(); - return segmentId; +void Script::initialiseLocals(SegManager *segMan) { + LocalVariables *locals = segMan->allocLocalsSegment(this); + if (locals) { + if (getSciVersion() > SCI_VERSION_0_EARLY) { + const byte *base = (const byte *)(_buf + getLocalsOffset()); + + for (uint16 i = 0; i < getLocalsCount(); i++) + locals->_locals[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(base + i * 2)); } else { - scr->freeScript(); + // In SCI0 early, locals are set at run time, thus zero them all here + for (uint16 i = 0; i < getLocalsCount(); i++) + locals->_locals[i] = NULL_REG; } - } else { - scr = segMan->allocateScript(scriptNum, &segmentId); } +} - scr->init(scriptNum, resMan); - scr->load(resMan); - +void Script::initialiseClasses(SegManager *segMan) { + const byte *seeker = 0; + uint16 mult = 0; + if (getSciVersion() >= SCI_VERSION_1_1) { - int heapStart = scr->getScriptSize(); - segMan->scriptInitialiseLocals(make_reg(segmentId, heapStart + 4)); - segMan->scriptInitialiseObjectsSci11(segmentId); - scr->relocate(make_reg(segmentId, READ_SCI11ENDIAN_UINT16(scr->_heapStart))); + seeker = _heapStart + 4 + READ_SCI11ENDIAN_UINT16(_heapStart + 2) * 2; + mult = 2; } else { - script_instantiate_sci0(scr, segmentId, segMan); - byte *relocationBlock = scr->findBlock(SCI_OBJ_POINTERS); - if (relocationBlock) - scr->relocate(make_reg(segmentId, relocationBlock - scr->_buf + 4)); + seeker = findBlock(SCI_OBJ_CLASS); + mult = 1; } - return segmentId; -} - -void script_uninstantiate_sci0(SegManager *segMan, int script_nr, SegmentId seg) { - bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); - reg_t reg = make_reg(seg, oldScriptHeader ? 2 : 0); - int objType, objLength = 0; - Script *scr = segMan->getScript(seg); + if (!seeker) + return; - // Make a pass over the object in order uninstantiate all superclasses + uint16 marker; + bool isClass; + uint16 classpos; + int16 species = 0; - do { - reg.offset += objLength; // Step over the last checked object + while (true) { + // In SCI0-SCI1, this is the segment type. In SCI11, it's a marker (0x1234) + marker = READ_SCI11ENDIAN_UINT16(seeker); + classpos = seeker - _buf; - objType = scr->getHeap(reg.offset); - if (!objType) + if (!marker) break; - objLength = scr->getHeap(reg.offset + 2); // use SEG_UGET_HEAP ?? - reg.offset += 4; // Step over header + if (getSciVersion() >= SCI_VERSION_1_1) { + isClass = (READ_SCI11ENDIAN_UINT16(seeker + 14) & kInfoFlagClass); // -info- selector + species = READ_SCI11ENDIAN_UINT16(seeker + 10); + } else { + isClass = (marker == SCI_OBJ_CLASS); + if (isClass) + species = READ_SCI11ENDIAN_UINT16(seeker + 12); + classpos += 12; + } - if ((objType == SCI_OBJ_OBJECT) || (objType == SCI_OBJ_CLASS)) { // object or class? - int superclass; + if (isClass) { + // WORKAROUND for an invalid species access in the demo of LSL2 + if (g_sci->getGameId() == GID_LSL2 && g_sci->isDemo() && species == (int)segMan->classTableSize()) + segMan->resizeClassTable(segMan->classTableSize() + 1); - reg.offset -= SCRIPT_OBJECT_MAGIC_OFFSET; + if (species < 0 || species >= (int)segMan->classTableSize()) + error("Invalid species %d(0x%x) not in interval [0,%d) while instantiating script %d\n", + species, species, segMan->classTableSize(), _nr); - superclass = scr->getHeap(reg.offset + SCRIPT_SUPERCLASS_OFFSET); // Get superclass... + SegmentId segmentId = segMan->getScriptSegment(_nr); + segMan->setClassOffset(species, make_reg(segmentId, classpos)); + } + + seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * mult; + } +} - if (superclass >= 0) { - int superclass_script = segMan->getClass(superclass).script; +void Script::initialiseObjectsSci0(SegManager *segMan, SegmentId segmentId) { + bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); + const byte *seeker = _buf + (oldScriptHeader ? 2 : 0); + + do { + uint16 objType = READ_SCI11ENDIAN_UINT16(seeker); + if (!objType) + break; - if (superclass_script == script_nr) { - if (scr->getLockers()) - scr->decrementLockers(); // Decrease lockers if this is us ourselves - } else - script_uninstantiate(segMan, superclass_script); - // Recurse to assure that the superclass lockers number gets decreased + switch (objType) { + case SCI_OBJ_OBJECT: + case SCI_OBJ_CLASS: + { + reg_t addr = make_reg(segmentId, seeker - _buf + 4); + Object *obj = scriptObjInit(addr); + obj->initSpecies(segMan, addr); + + if (!obj->initBaseObject(segMan, addr)) { + if (_nr == 202 && g_sci->getGameId() == GID_KQ5 && g_sci->getSciLanguage() == K_LANG_FRENCH) { + // Script 202 of KQ5 French has an invalid object. This is non-fatal. + } else { + error("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); + } + scriptObjRemove(addr); + } } + break; - reg.offset += SCRIPT_OBJECT_MAGIC_OFFSET; - } // if object or class + default: + break; + } - reg.offset -= 4; // Step back on header + seeker += READ_SCI11ENDIAN_UINT16(seeker + 2); + } while ((uint32)(seeker - _buf) < getScriptSize() - 2); - } while (objType != 0); + byte *relocationBlock = findBlock(SCI_OBJ_POINTERS); + if (relocationBlock) + relocate(make_reg(segmentId, relocationBlock - getBuf() + 4)); } -void script_uninstantiate(SegManager *segMan, int script_nr) { - SegmentId segment = segMan->getScriptSegment(script_nr); - Script *scr = segMan->getScriptIfLoaded(segment); +void Script::initialiseObjectsSci11(SegManager *segMan, SegmentId segmentId) { + const byte *seeker = _heapStart + 4 + READ_SCI11ENDIAN_UINT16(_heapStart + 2) * 2; - if (!scr) { // Is it already loaded? - //warning("unloading script 0x%x requested although not loaded", script_nr); - // This is perfectly valid SCI behaviour - return; - } + while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) { + reg_t reg = make_reg(segmentId, seeker - _buf); + Object *obj = scriptObjInit(reg); - scr->decrementLockers(); // One less locker + // Copy base from species class, as we need its selector IDs + obj->setSuperClassSelector( + segMan->getClassAddress(obj->getSuperClassSelector().offset, SCRIPT_GET_LOCK, NULL_REG)); - if (scr->getLockers() > 0) - return; + // If object is instance, get -propDict- from class and set it for this + // object. This is needed for ::isMemberOf() to work. + // Example testcase - room 381 of sq4cd - if isMemberOf() doesn't work, + // talk-clicks on the robot will act like clicking on ego + if (!obj->isClass()) { + reg_t classObject = obj->getSuperClassSelector(); + const Object *classObj = segMan->getObject(classObject); + obj->setPropDictSelector(classObj->getPropDictSelector()); + } - // Free all classtable references to this script - for (uint i = 0; i < segMan->classTableSize(); i++) - if (segMan->getClass(i).reg.segment == segment) - segMan->setClassOffset(i, NULL_REG); + // Set the -classScript- selector to the script number. + // FIXME: As this selector is filled in at run-time, it is likely + // that it is supposed to hold a pointer. The Obj::isKindOf method + // uses this selector together with -propDict- to compare classes. + // For the purpose of Obj::isKindOf, using the script number appears + // to be sufficient. + obj->setClassScriptSelector(make_reg(0, _nr)); - if (getSciVersion() < SCI_VERSION_1_1) - script_uninstantiate_sci0(segMan, script_nr, segment); - // FIXME: Add proper script uninstantiation for SCI 1.1 + seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2; + } - if (scr->getLockers()) - return; // if xxx.lockers > 0 + relocate(make_reg(segmentId, READ_SCI11ENDIAN_UINT16(_heapStart))); +} + +reg_t Script::findCanonicAddress(SegManager *segMan, reg_t addr) const { + addr.offset = 0; + return addr; +} - // Otherwise unload it completely - // Explanation: I'm starting to believe that this work is done by SCI itself. - scr->markDeleted(); +void Script::freeAtAddress(SegManager *segMan, reg_t addr) { + /* + debugC(2, kDebugLevelGC, "[GC] Freeing script %04x:%04x", PRINT_REG(addr)); + if (_localsSegment) + debugC(2, kDebugLevelGC, "[GC] Freeing locals %04x:0000", _localsSegment); + */ + + if (_markedAsDeleted) + segMan->deallocateScript(_nr); +} - debugC(kDebugLevelScripts, "Unloaded script 0x%x.", script_nr); +Common::Array<reg_t> Script::listAllDeallocatable(SegmentId segId) const { + const reg_t r = make_reg(segId, 0); + return Common::Array<reg_t>(&r, 1); +} - return; +Common::Array<reg_t> Script::listAllOutgoingReferences(reg_t addr) const { + Common::Array<reg_t> tmp; + if (addr.offset <= _bufSize && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(_buf + addr.offset)) { + const Object *obj = getObject(addr.offset); + if (obj) { + // Note all local variables, if we have a local variable environment + if (_localsSegment) + tmp.push_back(make_reg(_localsSegment, 0)); + + for (uint i = 0; i < obj->getVarCount(); i++) + tmp.push_back(obj->getVariable(i)); + } else { + error("Request for outgoing script-object reference at %04x:%04x failed", PRINT_REG(addr)); + } + } else { + /* warning("Unexpected request for outgoing script-object references at %04x:%04x", PRINT_REG(addr));*/ + /* Happens e.g. when we're looking into strings */ + } + return tmp; } +Common::Array<reg_t> Script::listObjectReferences() const { + Common::Array<reg_t> tmp; + + // Locals, if present + if (_localsSegment) + tmp.push_back(make_reg(_localsSegment, 0)); + + // All objects (may be classes, may be indirectly reachable) + ObjMap::iterator it; + const ObjMap::iterator end = _objects.end(); + for (it = _objects.begin(); it != end; ++it) { + tmp.push_back(it->_value.getPos()); + } + + return tmp; +} } // End of namespace Sci diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index e94e9f64e6..3817f8aae1 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -27,14 +27,13 @@ #define SCI_ENGINE_SCRIPT_H #include "common/str.h" +#include "sci/engine/segment.h" namespace Sci { struct EngineState; class ResourceManager; -#define SCI_SCRIPTS_NR 1000 - enum ScriptObjectTypes { SCI_OBJ_TERMINATOR, SCI_OBJ_OBJECT, @@ -49,160 +48,214 @@ enum ScriptObjectTypes { SCI_OBJ_LOCALVARS }; -// Opcode formats -enum opcode_format { - Script_Invalid = -1, - Script_None = 0, - Script_Byte, - Script_SByte, - Script_Word, - Script_SWord, - Script_Variable, - Script_SVariable, - Script_SRelative, - Script_Property, - Script_Global, - Script_Local, - Script_Temp, - Script_Param, - Script_Offset, - Script_End -}; +typedef Common::HashMap<uint16, Object> ObjMap; -enum sci_opcodes { - op_bnot = 0x00, // 000 - op_add = 0x01, // 001 - op_sub = 0x02, // 002 - op_mul = 0x03, // 003 - op_div = 0x04, // 004 - op_mod = 0x05, // 005 - op_shr = 0x06, // 006 - op_shl = 0x07, // 007 - op_xor = 0x08, // 008 - op_and = 0x09, // 009 - op_or = 0x0a, // 010 - op_neg = 0x0b, // 011 - op_not = 0x0c, // 012 - op_eq_ = 0x0d, // 013 - op_ne_ = 0x0e, // 014 - op_gt_ = 0x0f, // 015 - op_ge_ = 0x10, // 016 - op_lt_ = 0x11, // 017 - op_le_ = 0x12, // 018 - op_ugt_ = 0x13, // 019 - op_uge_ = 0x14, // 020 - op_ult_ = 0x15, // 021 - op_ule_ = 0x16, // 022 - op_bt = 0x17, // 023 - op_bnt = 0x18, // 024 - op_jmp = 0x19, // 025 - op_ldi = 0x1a, // 026 - op_push = 0x1b, // 027 - op_pushi = 0x1c, // 028 - op_toss = 0x1d, // 029 - op_dup = 0x1e, // 030 - op_link = 0x1f, // 031 - op_call = 0x20, // 032 - op_callk = 0x21, // 033 - op_callb = 0x22, // 034 - op_calle = 0x23, // 035 - op_ret = 0x24, // 036 - op_send = 0x25, // 037 - // dummy 0x26, // 038 - // dummy 0x27, // 039 - op_class = 0x28, // 040 - // dummy 0x29, // 041 - op_self = 0x2a, // 042 - op_super = 0x2b, // 043 - op_rest = 0x2c, // 044 - op_lea = 0x2d, // 045 - op_selfID = 0x2e, // 046 - // dummy 0x2f // 047 - op_pprev = 0x30, // 048 - op_pToa = 0x31, // 049 - op_aTop = 0x32, // 050 - op_pTos = 0x33, // 051 - op_sTop = 0x34, // 052 - op_ipToa = 0x35, // 053 - op_dpToa = 0x36, // 054 - op_ipTos = 0x37, // 055 - op_dpTos = 0x38, // 056 - op_lofsa = 0x39, // 057 - op_lofss = 0x3a, // 058 - op_push0 = 0x3b, // 059 - op_push1 = 0x3c, // 060 - op_push2 = 0x3d, // 061 - op_pushSelf = 0x3e, // 062 - op_line = 0x3f, // 063 - op_lag = 0x40, // 064 - op_lal = 0x41, // 065 - op_lat = 0x42, // 066 - op_lap = 0x43, // 067 - op_lsg = 0x44, // 068 - op_lsl = 0x45, // 069 - op_lst = 0x46, // 070 - op_lsp = 0x47, // 071 - op_lagi = 0x48, // 072 - op_lali = 0x49, // 073 - op_lati = 0x4a, // 074 - op_lapi = 0x4b, // 075 - op_lsgi = 0x4c, // 076 - op_lsli = 0x4d, // 077 - op_lsti = 0x4e, // 078 - op_lspi = 0x4f, // 079 - op_sag = 0x50, // 080 - op_sal = 0x51, // 081 - op_sat = 0x52, // 082 - op_sap = 0x53, // 083 - op_ssg = 0x54, // 084 - op_ssl = 0x55, // 085 - op_sst = 0x56, // 086 - op_ssp = 0x57, // 087 - op_sagi = 0x58, // 088 - op_sali = 0x59, // 089 - op_sati = 0x5a, // 090 - op_sapi = 0x5b, // 091 - op_ssgi = 0x5c, // 092 - op_ssli = 0x5d, // 093 - op_ssti = 0x5e, // 094 - op_sspi = 0x5f, // 095 - op_plusag = 0x60, // 096 - op_plusal = 0x61, // 097 - op_plusat = 0x62, // 098 - op_plusap = 0x63, // 099 - op_plussg = 0x64, // 100 - op_plussl = 0x65, // 101 - op_plusst = 0x66, // 102 - op_plussp = 0x67, // 103 - op_plusagi = 0x68, // 104 - op_plusali = 0x69, // 105 - op_plusati = 0x6a, // 106 - op_plusapi = 0x6b, // 107 - op_plussgi = 0x6c, // 108 - op_plussli = 0x6d, // 109 - op_plussti = 0x6e, // 110 - op_plusspi = 0x6f, // 111 - op_minusag = 0x70, // 112 - op_minusal = 0x71, // 113 - op_minusat = 0x72, // 114 - op_minusap = 0x73, // 115 - op_minussg = 0x74, // 116 - op_minussl = 0x75, // 117 - op_minusst = 0x76, // 118 - op_minussp = 0x77, // 119 - op_minusagi = 0x78, // 120 - op_minusali = 0x79, // 121 - op_minusati = 0x7a, // 122 - op_minusapi = 0x7b, // 123 - op_minussgi = 0x7c, // 124 - op_minussli = 0x7d, // 125 - op_minussti = 0x7e, // 126 - op_minusspi = 0x7f // 127 -}; +class Script : public SegmentObj { +private: + int _nr; /**< Script number */ + byte *_buf; /**< Static data buffer, or NULL if not used */ + byte *_heapStart; /**< Start of heap if SCI1.1, NULL otherwise */ + + int _lockers; /**< Number of classes and objects that require this script */ + size_t _scriptSize; + size_t _heapSize; + uint16 _bufSize; + + const uint16 *_exportTable; /**< Abs. offset of the export table or 0 if not present */ + uint16 _numExports; /**< Number of entries in the exports table */ + + const byte *_synonyms; /**< Synonyms block or 0 if not present*/ + uint16 _numSynonyms; /**< Number of entries in the synonyms block */ + + int _localsOffset; + uint16 _localsCount; + + bool _markedAsDeleted; + +public: + /** + * Table for objects, contains property variables. + * Indexed by the TODO offset. + */ + ObjMap _objects; + SegmentId _localsSegment; /**< The local variable segment */ + LocalVariables *_localsBlock; + +public: + int getLocalsOffset() const { return _localsOffset; } + uint16 getLocalsCount() const { return _localsCount; } + + uint32 getScriptSize() const { return _scriptSize; } + uint32 getHeapSize() const { return _heapSize; } + uint32 getBufSize() const { return _bufSize; } + const byte *getBuf(uint offset = 0) const { return _buf + offset; } + + int getScriptNumber() const { return _nr; } + +public: + Script(); + ~Script(); + + void freeScript(); + void init(int script_nr, ResourceManager *resMan); + void load(ResourceManager *resMan); + + virtual bool isValidOffset(uint16 offset) const; + virtual SegmentRef dereference(reg_t pointer); + virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const; + virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr); + virtual Common::Array<reg_t> listAllDeallocatable(SegmentId segId) const; + virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const; + + /** + * Return a list of all references to objects in this script + * (and also to the locals segment, if any). + * Used by the garbage collector. + * @return a list of outgoing references within the object + */ + Common::Array<reg_t> listObjectReferences() const; + + virtual void saveLoadWithSerializer(Common::Serializer &ser); + + Object *getObject(uint16 offset); + const Object *getObject(uint16 offset) const; + + /** + * Initializes an object within the segment manager + * @param obj_pos Location (segment, offset) of the object. It must + * point to the beginning of the script/class block + * (as opposed to what the VM considers to be the + * object location) + * @returns A newly created Object describing the object, + * stored within the relevant script + */ + Object *scriptObjInit(reg_t obj_pos, bool fullObjectInit = true); + + /** + * Removes a script object + * @param obj_pos Location (segment, offset) of the object. + */ + void scriptObjRemove(reg_t obj_pos); -extern opcode_format g_opcode_formats[128][4]; + /** + * Initializes the script's local variables + * @param segMan A reference to the segment manager + */ + void initialiseLocals(SegManager *segMan); -void script_adjust_opcode_formats(EngineState *s); + /** + * Adds the script's classes to the segment manager's class table + * @param segMan A reference to the segment manager + */ + void initialiseClasses(SegManager *segMan); + + /** + * Initializes the script's objects (SCI0) + * @param segMan A reference to the segment manager + * @param segmentId The script's segment id + */ + void initialiseObjectsSci0(SegManager *segMan, SegmentId segmentId); + + /** + * Initializes the script's objects (SCI1.1+) + * @param segMan A reference to the segment manager + * @param segmentId The script's segment id + */ + void initialiseObjectsSci11(SegManager *segMan, SegmentId segmentId); + + // script lock operations + + /** Increments the number of lockers of this script by one. */ + void incrementLockers(); + + /** Decrements the number of lockers of this script by one. */ + void decrementLockers(); + + /** + * Retrieves the number of locks held on this script. + * @return the number of locks held on the previously identified script + */ + int getLockers() const; + + /** Sets the number of locks held on this script. */ + void setLockers(int lockers); + + /** + * Retrieves a pointer to the exports of this script + * @return pointer to the exports. + */ + const uint16 *getExportTable() const { return _exportTable; } + + /** + * Retrieves the number of exports of script. + * @return the number of exports of this script + */ + uint16 getExportsNr() const { return _numExports; } + + /** + * Retrieves a pointer to the synonyms associated with this script + * @return pointer to the synonyms, in non-parsed format. + */ + const byte *getSynonyms() const { return _synonyms; } + + /** + * Retrieves the number of synonyms associated with this script. + * @return the number of synonyms associated with this script + */ + uint16 getSynonymsNr() const { return _numSynonyms; } + + /** + * Validate whether the specified public function is exported by + * the script in the specified segment. + * @param pubfunct Index of the function to validate + * @return NULL if the public function is invalid, its + * offset into the script's segment otherwise + */ + uint16 validateExportFunc(int pubfunct); + + /** + * Marks the script as deleted. + * This will not actually delete the script. If references remain present on the + * heap or the stack, the script will stay in memory in a quasi-deleted state until + * either unreachable (resulting in its eventual deletion) or reloaded (resulting + * in its data being updated). + */ + void markDeleted() { + _markedAsDeleted = true; + } + + /** + * Determines whether the script is marked as being deleted. + */ + bool isMarkedAsDeleted() const { + return _markedAsDeleted; + } + + /** + * Copies a byte string into a script's heap representation. + * @param dst script-relative offset of the destination area + * @param src pointer to the data source location + * @param n number of bytes to copy + */ + void mcpyInOut(int dst, const void *src, size_t n); + + /** + * Finds the pointer where a block of a specific type starts from + */ + byte *findBlock(int type); + +private: + /** + * Processes a relocation block witin a script + * This function is idempotent, but it must only be called after all + * objects have been instantiated, or a run-time error will occur. + * @param obj_pos Location (segment, offset) of the block + * @return Location of the relocation block + */ + void relocate(reg_t block); + + bool relocateLocal(SegmentId segment, int location); +}; } // End of namespace Sci diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index b465ab3d4e..915a6fa994 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -63,15 +63,11 @@ const char *opcodeNames[] = { "-sli", "-sti", "-spi" }; -extern const char *selector_name(EngineState *s, int selector); - -DebugState g_debugState; - // Disassembles one command from the heap, returns address of next command or 0 if a ret was encountered. reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecode) { SegmentObj *mobj = s->_segMan->getSegment(pos.segment, SEG_TYPE_SCRIPT); Script *script_entity = NULL; - byte *scr; + const byte *scr; int scr_size; reg_t retval = make_reg(pos.segment, pos.offset + 1); uint16 param_value; @@ -84,7 +80,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod } else script_entity = (Script *)mobj; - scr = script_entity->_buf; + scr = script_entity->getBuf(); scr_size = script_entity->getBufSize(); if (pos.offset >= scr_size) { @@ -197,7 +193,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod if (!obj) warning("Attempted to reference on non-object at %04x:%04x", PRINT_REG(s->xs->objp)); else - printf(" (%s)", selector_name(s, obj->propertyOffsetToId(s->_segMan, scr[pos.offset + 1]))); + printf(" (%s)", g_sci->getKernel()->getSelectorName(obj->propertyOffsetToId(s->_segMan, scr[pos.offset + 1])).c_str()); } } @@ -205,12 +201,12 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod if (pos == s->xs->addr.pc) { // Extra information if debugging the current opcode if (opcode == op_callk) { - int stackframe = (scr[pos.offset + 2] >> 1) + (s->restAdjustCur); + int stackframe = (scr[pos.offset + 2] >> 1) + (s->restAdjust); int argc = ((s->xs->sp)[- stackframe - 1]).offset; bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); if (!oldScriptHeader) - argc += (s->restAdjustCur); + argc += (s->restAdjust); printf(" Kernel params: ("); @@ -221,7 +217,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod } printf(")\n"); } else if ((opcode == op_send) || (opcode == op_self)) { - int restmod = s->restAdjustCur; + int restmod = s->restAdjust; int stackframe = (scr[pos.offset + 1] >> 1) + restmod; reg_t *sb = s->xs->sp; uint16 selector; @@ -244,7 +240,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod if (!name) name = "<invalid>"; - printf(" %s::%s[", name, (selector > kernel->getSelectorNamesSize()) ? "<invalid>" : selector_name(s, selector)); + printf(" %s::%s[", name, g_sci->getKernel()->getSelectorName(selector).c_str()); switch (lookupSelector(s->_segMan, called_obj_addr, selector, 0, &fun_ref)) { case kSelectorMethod: @@ -279,90 +275,76 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod } -void script_debug(EngineState *s) { - // Do we support a separate console? +void SciEngine::scriptDebug() { + EngineState *s = _gamestate; + if (_debugState.seeking && !_debugState.breakpointWasHit) { // Are we looking for something special? + if (_debugState.seeking == kDebugSeekStepOver) { + // are we above seek-level? resume then + if (_debugState.seekLevel < (int)s->_executionStack.size()) + return; + _debugState.seeking = kDebugSeekNothing; + } -#if 0 - if (sci_debug_flags & _DEBUG_FLAG_LOGGING) { - printf("%d: acc=%04x:%04x ", script_step_counter, PRINT_REG(s->r_acc)); - disassemble(s, s->xs->addr.pc, 0, 1); - if (s->seeking == kDebugSeekGlobal) - printf("Global %d (0x%x) = %04x:%04x\n", s->seekSpecial, - s->seekSpecial, PRINT_REG(s->script_000->_localsBlock->_locals[s->seekSpecial])); - } -#endif + if (_debugState.seeking != kDebugSeekNothing) { + const reg_t pc = s->xs->addr.pc; + SegmentObj *mobj = s->_segMan->getSegment(pc.segment, SEG_TYPE_SCRIPT); + + if (mobj) { + Script *scr = (Script *)mobj; + const byte *code_buf = scr->getBuf(); + int code_buf_size = scr->getBufSize(); + int opcode = pc.offset >= code_buf_size ? 0 : code_buf[pc.offset]; + int op = opcode >> 1; + int paramb1 = pc.offset + 1 >= code_buf_size ? 0 : code_buf[pc.offset + 1]; + int paramf1 = (opcode & 1) ? paramb1 : (pc.offset + 2 >= code_buf_size ? 0 : (int16)READ_SCI11ENDIAN_UINT16(code_buf + pc.offset + 1)); + + switch (_debugState.seeking) { + case kDebugSeekSpecialCallk: + if (paramb1 != _debugState.seekSpecial) + return; + + case kDebugSeekCallk: + if (op != op_callk) + return; + break; -#if 0 - if (!g_debugState.debugging) - return; -#endif - - if (g_debugState.seeking && !g_debugState.breakpointWasHit) { // Are we looking for something special? - SegmentObj *mobj = s->_segMan->getSegment(s->xs->addr.pc.segment, SEG_TYPE_SCRIPT); - - if (mobj) { - Script *scr = (Script *)mobj; - byte *code_buf = scr->_buf; - int code_buf_size = scr->getBufSize(); - int opcode = s->xs->addr.pc.offset >= code_buf_size ? 0 : code_buf[s->xs->addr.pc.offset]; - int op = opcode >> 1; - int paramb1 = s->xs->addr.pc.offset + 1 >= code_buf_size ? 0 : code_buf[s->xs->addr.pc.offset + 1]; - int paramf1 = (opcode & 1) ? paramb1 : (s->xs->addr.pc.offset + 2 >= code_buf_size ? 0 : (int16)READ_SCI11ENDIAN_UINT16(code_buf + s->xs->addr.pc.offset + 1)); - - switch (g_debugState.seeking) { - case kDebugSeekSpecialCallk: - if (paramb1 != g_debugState.seekSpecial) - return; - - case kDebugSeekCallk: { - if (op != op_callk) - return; - break; - } + case kDebugSeekLevelRet: + if ((op != op_ret) || (_debugState.seekLevel < (int)s->_executionStack.size()-1)) + return; + break; - case kDebugSeekLevelRet: { - if ((op != op_ret) || (g_debugState.seekLevel < (int)s->_executionStack.size()-1)) - return; - break; - } + case kDebugSeekGlobal: + if (op < op_sag) + return; + if ((op & 0x3) > 1) + return; // param or temp + if ((op & 0x3) && s->_executionStack.back().local_segment > 0) + return; // locals and not running in script.000 + if (paramf1 != _debugState.seekSpecial) + return; // CORRECT global? + break; - case kDebugSeekGlobal: - if (op < op_sag) - return; - if ((op & 0x3) > 1) - return; // param or temp - if ((op & 0x3) && s->_executionStack.back().local_segment > 0) - return; // locals and not running in script.000 - if (paramf1 != g_debugState.seekSpecial) - return; // CORRECT global? - break; - - case kDebugSeekSO: - // FIXME: Unhandled? - break; - - case kDebugSeekNothing: - // We seek nothing, so just continue - break; - } + default: + break; + } - g_debugState.seeking = kDebugSeekNothing; - // OK, found whatever we were looking for + _debugState.seeking = kDebugSeekNothing; + } } + // OK, found whatever we were looking for } - printf("Step #%d\n", s->script_step_counter); + printf("Step #%d\n", s->scriptStepCounter); disassemble(s, s->xs->addr.pc, 0, 1); - if (g_debugState.runningStep) { - g_debugState.runningStep--; + if (_debugState.runningStep) { + _debugState.runningStep--; return; } - g_debugState.debugging = false; + _debugState.debugging = false; - Console *con = ((Sci::SciEngine*)g_engine)->getSciDebugger(); - con->attach(); + _console->attach(); } void Kernel::dumpScriptObject(char *data, int seeker, int objsize) { @@ -491,19 +473,17 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) { dumpScriptObject((char *)script->data, seeker, objsize); break; - case SCI_OBJ_CODE: { + case SCI_OBJ_CODE: printf("Code\n"); Common::hexdump(script->data + seeker, objsize - 4, 16, seeker); - }; - break; + break; - case 3: { + case 3: printf("<unknown>\n"); Common::hexdump(script->data + seeker, objsize - 4, 16, seeker); - }; - break; + break; - case SCI_OBJ_SAID: { + case SCI_OBJ_SAID: printf("Said\n"); Common::hexdump(script->data + seeker, objsize - 4, 16, seeker); @@ -551,46 +531,40 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) { } } printf("\n"); - } - break; + break; - case SCI_OBJ_STRINGS: { + case SCI_OBJ_STRINGS: printf("Strings\n"); while (script->data [seeker]) { printf("%04x: %s\n", seeker, script->data + seeker); seeker += strlen((char *)script->data + seeker) + 1; } seeker++; // the ending zero byte - }; - break; + break; case SCI_OBJ_CLASS: dumpScriptClass((char *)script->data, seeker, objsize); break; - case SCI_OBJ_EXPORTS: { + case SCI_OBJ_EXPORTS: printf("Exports\n"); Common::hexdump((unsigned char *)script->data + seeker, objsize - 4, 16, seeker); - }; - break; + break; - case SCI_OBJ_POINTERS: { + case SCI_OBJ_POINTERS: printf("Pointers\n"); Common::hexdump(script->data + seeker, objsize - 4, 16, seeker); - }; - break; + break; - case 9: { + case 9: printf("<unknown>\n"); Common::hexdump(script->data + seeker, objsize - 4, 16, seeker); - }; - break; + break; - case SCI_OBJ_LOCALVARS: { + case SCI_OBJ_LOCALVARS: printf("Local vars\n"); Common::hexdump(script->data + seeker, objsize - 4, 16, seeker); - }; - break; + break; default: printf("Unsupported!\n"); diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 4d3e6f754e..ef2279e492 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -26,6 +26,7 @@ #include "sci/sci.h" #include "sci/engine/seg_manager.h" #include "sci/engine/state.h" +#include "sci/engine/script.h" namespace Sci { @@ -39,14 +40,14 @@ enum { SegManager::SegManager(ResourceManager *resMan) { _heap.push_back(0); - Clones_seg_id = 0; - Lists_seg_id = 0; - Nodes_seg_id = 0; - Hunks_seg_id = 0; + _clonesSegId = 0; + _listsSegId = 0; + _nodesSegId = 0; + _hunksSegId = 0; #ifdef ENABLE_SCI32 - Arrays_seg_id = 0; - String_seg_id = 0; + _arraysSegId = 0; + _stringSegId = 0; #endif _resMan = resMan; @@ -70,10 +71,10 @@ void SegManager::resetSegMan() { // And reinitialize _heap.push_back(0); - Clones_seg_id = 0; - Lists_seg_id = 0; - Nodes_seg_id = 0; - Hunks_seg_id = 0; + _clonesSegId = 0; + _listsSegId = 0; + _nodesSegId = 0; + _hunksSegId = 0; // Reinitialize class table _classTable.clear(); @@ -81,10 +82,10 @@ void SegManager::resetSegMan() { } void SegManager::initSysStrings() { - sysStrings = (SystemStrings *)allocSegment(new SystemStrings(), &sysStringsSegment); + _sysStrings = (SystemStrings *)allocSegment(new SystemStrings(), &_sysStringsSegId); // Allocate static buffer for savegame and CWD directories - SystemString *strSaveDir = &sysStrings->_strings[SYS_STRING_SAVEDIR]; + SystemString *strSaveDir = getSystemString(SYS_STRING_SAVEDIR); strSaveDir->_name = "savedir"; strSaveDir->_maxSize = MAX_SAVE_DIR_SIZE; strSaveDir->_value = (char *)calloc(MAX_SAVE_DIR_SIZE, sizeof(char)); @@ -93,23 +94,17 @@ void SegManager::initSysStrings() { ::strcpy(strSaveDir->_value, ""); // Allocate static buffer for the parser base - SystemString *strParserBase = &sysStrings->_strings[SYS_STRING_PARSER_BASE]; + SystemString *strParserBase = getSystemString(SYS_STRING_PARSER_BASE); strParserBase->_name = "parser-base"; strParserBase->_maxSize = MAX_PARSER_BASE; strParserBase->_value = (char *)calloc(MAX_PARSER_BASE, sizeof(char)); } SegmentId SegManager::findFreeSegment() const { - // FIXME: This is a very crude approach: We find a free segment id by scanning - // from the start. This can be slow if the number of segments becomes large. - // Optimizations are possible and easy, but I refrain from doing any until this - // refactoring is complete. - // One very simple yet probably effective approach would be to add - // "int firstFreeSegment", which is updated when allocating/freeing segments. - // There are some scenarios where it performs badly, but we should first check - // whether those occur at all. If so, there are easy refinements that deal - // with this. Finally, we could switch to a more elaborate scheme, - // such as keeping track of all free segments. But I doubt this is necessary. + // The following is a very crude approach: We find a free segment id by + // scanning from the start. This can be slow if the number of segments + // becomes large. Optimizations are possible and easy, but I'll refrain + // from attempting any until we determine we actually need it. uint seg = 1; while (seg < _heap.size() && _heap[seg]) { ++seg; @@ -162,7 +157,7 @@ int SegManager::deallocate(SegmentId seg, bool recursive) { if (mobj->getType() == SEG_TYPE_SCRIPT) { Script *scr = (Script *)mobj; - _scriptSegMap.erase(scr->_nr); + _scriptSegMap.erase(scr->getScriptNumber()); if (recursive && scr->_localsSegment) deallocate(scr->_localsSegment, recursive); } @@ -173,12 +168,12 @@ int SegManager::deallocate(SegmentId seg, bool recursive) { return 1; } -bool SegManager::isHeapObject(reg_t pos) { +bool SegManager::isHeapObject(reg_t pos) const { const Object *obj = getObject(pos); if (obj == NULL || (obj && obj->isFreed())) return false; Script *scr = getScriptIfLoaded(pos.segment); - return !(scr && scr->_markedAsDeleted); + return !(scr && scr->isMarkedAsDeleted()); } void SegManager::deallocateScript(int script_nr) { @@ -199,36 +194,36 @@ Script *SegManager::getScript(const SegmentId seg) { return (Script *)_heap[seg]; } -Script *SegManager::getScriptIfLoaded(const SegmentId seg) { +Script *SegManager::getScriptIfLoaded(const SegmentId seg) const { if (seg < 1 || (uint)seg >= _heap.size() || !_heap[seg] || _heap[seg]->getType() != SEG_TYPE_SCRIPT) return 0; return (Script *)_heap[seg]; } -SegmentId SegManager::findSegmentByType(int type) { +SegmentId SegManager::findSegmentByType(int type) const { for (uint i = 0; i < _heap.size(); i++) if (_heap[i] && _heap[i]->getType() == type) return i; return 0; } -SegmentObj *SegManager::getSegmentObj(SegmentId seg) { +SegmentObj *SegManager::getSegmentObj(SegmentId seg) const { if (seg < 1 || (uint)seg >= _heap.size() || !_heap[seg]) return 0; return _heap[seg]; } -SegmentType SegManager::getSegmentType(SegmentId seg) { +SegmentType SegManager::getSegmentType(SegmentId seg) const { if (seg < 1 || (uint)seg >= _heap.size() || !_heap[seg]) return SEG_TYPE_INVALID; return _heap[seg]->getType(); } -SegmentObj *SegManager::getSegment(SegmentId seg, SegmentType type) { +SegmentObj *SegManager::getSegment(SegmentId seg, SegmentType type) const { return getSegmentType(seg) == type ? _heap[seg] : NULL; } -Object *SegManager::getObject(reg_t pos) { +Object *SegManager::getObject(reg_t pos) const { SegmentObj *mobj = getSegmentObj(pos.segment); Object *obj = NULL; @@ -242,7 +237,7 @@ Object *SegManager::getObject(reg_t pos) { } else if (mobj->getType() == SEG_TYPE_SCRIPT) { Script *scr = (Script *)mobj; if (pos.offset <= scr->getBufSize() && pos.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET - && RAW_IS_OBJECT(scr->_buf + pos.offset)) { + && RAW_IS_OBJECT(scr->getBuf(pos.offset))) { obj = scr->getObject(pos.offset); } } @@ -268,78 +263,55 @@ const char *SegManager::getObjectName(reg_t pos) { } reg_t SegManager::findObjectByName(const Common::String &name, int index) { - reg_t retVal = NULL_REG; + Common::Array<reg_t> result; + uint i; // Now all values are available; iterate over all objects. - int timesFound = 0; - for (uint i = 0; i < _heap.size(); i++) { - SegmentObj *mobj = _heap[i]; - int idx = 0; - int max_index = 0; - ObjMap::iterator it; - Script *scr = 0; - CloneTable *ct = 0; - - if (mobj) { - if (mobj->getType() == SEG_TYPE_SCRIPT) { - scr = (Script *)mobj; - max_index = scr->_objects.size(); - it = scr->_objects.begin(); - } else if (mobj->getType() == SEG_TYPE_CLONES) { - ct = (CloneTable *)mobj; - max_index = ct->_table.size(); - } - } + for (i = 0; i < _heap.size(); i++) { + const SegmentObj *mobj = _heap[i]; + + if (!mobj) + continue; + + reg_t objpos = make_reg(i, 0); - // It's a script or a clone table, scan all objects in it - for (; idx < max_index; ++idx) { - const Object *obj = NULL; - reg_t objpos; - objpos.offset = 0; - objpos.segment = i; - - if (mobj->getType() == SEG_TYPE_SCRIPT) { - obj = &(it->_value); - objpos.offset = obj->getPos().offset; - ++it; - } else if (mobj->getType() == SEG_TYPE_CLONES) { + if (mobj->getType() == SEG_TYPE_SCRIPT) { + // It's a script, scan all objects in it + const Script *scr = (const Script *)mobj; + for (ObjMap::const_iterator it = scr->_objects.begin(); it != scr->_objects.end(); ++it) { + objpos.offset = it->_value.getPos().offset; + if (name == getObjectName(objpos)) + result.push_back(objpos); + } + } else if (mobj->getType() == SEG_TYPE_CLONES) { + // It's clone table, scan all objects in it + const CloneTable *ct = (const CloneTable *)mobj; + for (uint idx = 0; idx < ct->_table.size(); ++idx) { if (!ct->isValidEntry(idx)) continue; - obj = &(ct->_table[idx]); - objpos.offset = idx; - } - const char *objname = getObjectName(objpos); - if (name == objname) { - // Found a match! - if ((index < 0) && (timesFound > 0)) { - if (timesFound == 1) { - // First time we realized the ambiguity - printf("Ambiguous:\n"); - printf(" %3x: [%04x:%04x] %s\n", 0, PRINT_REG(retVal), name.c_str()); - } - printf(" %3x: [%04x:%04x] %s\n", timesFound, PRINT_REG(objpos), name.c_str()); - } - if (index < 0 || timesFound == index) - retVal = objpos; - ++timesFound; + objpos.offset = idx; + if (name == getObjectName(objpos)) + result.push_back(objpos); } } - } - if (!timesFound) + if (result.empty()) return NULL_REG; - if (timesFound > 1 && index < 0) { - printf("Ambiguous: Aborting.\n"); + if (result.size() > 1 && index < 0) { + printf("Ambiguous:\n"); + for (i = 0; i < result.size(); i++) + printf(" %3x: [%04x:%04x] %s\n", i, PRINT_REG(result[i]), name.c_str()); return NULL_REG; // Ambiguous } - if (timesFound <= index) + if (index < 0) + return result[0]; + else if (result.size() <= (uint)index) return NULL_REG; // Not found - - return retVal; + return result[index]; } // validate the seg @@ -366,7 +338,7 @@ SegmentId SegManager::getScriptSegment(int script_nr, ScriptLoadType load) { SegmentId segment; if ((load & SCRIPT_GET_LOAD) == SCRIPT_GET_LOAD) - script_instantiate(_resMan, this, script_nr); + instantiateScript(script_nr); segment = getScriptSegment(script_nr); @@ -377,8 +349,8 @@ SegmentId SegManager::getScriptSegment(int script_nr, ScriptLoadType load) { return segment; } -LocalVariables *SegManager::allocLocalsSegment(Script *scr, int count) { - if (!count) { // No locals +LocalVariables *SegManager::allocLocalsSegment(Script *scr) { + if (!scr->getLocalsCount()) { // No locals scr->_localsSegment = 0; scr->_localsBlock = NULL; return NULL; @@ -389,13 +361,13 @@ LocalVariables *SegManager::allocLocalsSegment(Script *scr, int count) { locals = (LocalVariables *)_heap[scr->_localsSegment]; VERIFY(locals != NULL, "Re-used locals segment was NULL'd out"); VERIFY(locals->getType() == SEG_TYPE_LOCALS, "Re-used locals segment did not consist of local variables"); - VERIFY(locals->script_id == scr->_nr, "Re-used locals segment belonged to other script"); + VERIFY(locals->script_id == scr->getScriptNumber(), "Re-used locals segment belonged to other script"); } else locals = (LocalVariables *)allocSegment(new LocalVariables(), &scr->_localsSegment); scr->_localsBlock = locals; - locals->script_id = scr->_nr; - locals->_locals.resize(count); + locals->script_id = scr->getScriptNumber(); + locals->_locals.resize(scr->getLocalsCount()); return locals; } @@ -408,6 +380,12 @@ DataStack *SegManager::allocateStack(int size, SegmentId *segid) { retval->_entries = (reg_t *)calloc(size, sizeof(reg_t)); retval->_capacity = size; + // SSCI initializes the stack with "S" characters (uppercase S in SCI0-SCI1, + // lowercase s in SCI0 and SCI11) - probably stands for "stack" + byte filler = (getSciVersion() >= SCI_VERSION_01 && getSciVersion() <= SCI_VERSION_1_LATE) ? 'S' : 's'; + for (int i = 0; i < size; i++) + retval->_entries[i] = make_reg(0, filler); + return retval; } @@ -431,13 +409,13 @@ reg_t SegManager::allocateHunkEntry(const char *hunk_type, int size) { HunkTable *table; int offset; - if (!Hunks_seg_id) - allocSegment(new HunkTable(), &(Hunks_seg_id)); - table = (HunkTable *)_heap[Hunks_seg_id]; + if (!_hunksSegId) + allocSegment(new HunkTable(), &(_hunksSegId)); + table = (HunkTable *)_heap[_hunksSegId]; offset = table->allocEntry(); - reg_t addr = make_reg(Hunks_seg_id, offset); + reg_t addr = make_reg(_hunksSegId, offset); Hunk *h = &(table->_table[offset]); if (!h) @@ -454,7 +432,7 @@ byte *SegManager::getHunkPointer(reg_t addr) { HunkTable *ht = (HunkTable *)getSegment(addr.segment, SEG_TYPE_HUNK); if (!ht || !ht->isValidEntry(addr.offset)) { - warning("getHunkPointer() with invalid handle"); + // Valid SCI behavior, e.g. when loading/quitting return NULL; } @@ -465,61 +443,28 @@ Clone *SegManager::allocateClone(reg_t *addr) { CloneTable *table; int offset; - if (!Clones_seg_id) - table = (CloneTable *)allocSegment(new CloneTable(), &(Clones_seg_id)); + if (!_clonesSegId) + table = (CloneTable *)allocSegment(new CloneTable(), &(_clonesSegId)); else - table = (CloneTable *)_heap[Clones_seg_id]; + table = (CloneTable *)_heap[_clonesSegId]; offset = table->allocEntry(); - *addr = make_reg(Clones_seg_id, offset); + *addr = make_reg(_clonesSegId, offset); return &(table->_table[offset]); } -void SegManager::reconstructClones() { - for (uint i = 0; i < _heap.size(); i++) { - if (_heap[i]) { - SegmentObj *mobj = _heap[i]; - if (mobj->getType() == SEG_TYPE_CLONES) { - CloneTable *ct = (CloneTable *)mobj; - - for (uint j = 0; j < ct->_table.size(); j++) { - // Check if the clone entry is used - uint entryNum = (uint)ct->first_free; - bool isUsed = true; - while (entryNum != ((uint) CloneTable::HEAPENTRY_INVALID)) { - if (entryNum == j) { - isUsed = false; - break; - } - entryNum = ct->_table[entryNum].next_free; - } - - if (!isUsed) - continue; - - CloneTable::Entry &seeker = ct->_table[j]; - const Object *baseObj = getObject(seeker.getSpeciesSelector()); - seeker.cloneFromObject(baseObj); - if (!baseObj) - warning("Clone entry without a base class: %d", j); - } // end for - } // end if - } // end if - } // end for -} - List *SegManager::allocateList(reg_t *addr) { ListTable *table; int offset; - if (!Lists_seg_id) - allocSegment(new ListTable(), &(Lists_seg_id)); - table = (ListTable *)_heap[Lists_seg_id]; + if (!_listsSegId) + allocSegment(new ListTable(), &(_listsSegId)); + table = (ListTable *)_heap[_listsSegId]; offset = table->allocEntry(); - *addr = make_reg(Lists_seg_id, offset); + *addr = make_reg(_listsSegId, offset); return &(table->_table[offset]); } @@ -527,36 +472,36 @@ Node *SegManager::allocateNode(reg_t *addr) { NodeTable *table; int offset; - if (!Nodes_seg_id) - allocSegment(new NodeTable(), &(Nodes_seg_id)); - table = (NodeTable *)_heap[Nodes_seg_id]; + if (!_nodesSegId) + allocSegment(new NodeTable(), &(_nodesSegId)); + table = (NodeTable *)_heap[_nodesSegId]; offset = table->allocEntry(); - *addr = make_reg(Nodes_seg_id, offset); + *addr = make_reg(_nodesSegId, offset); return &(table->_table[offset]); } reg_t SegManager::newNode(reg_t value, reg_t key) { - reg_t nodebase; - Node *n = allocateNode(&nodebase); + reg_t nodeRef; + Node *n = allocateNode(&nodeRef); n->pred = n->succ = NULL_REG; n->key = key; n->value = value; - return nodebase; + return nodeRef; } List *SegManager::lookupList(reg_t addr) { if (getSegmentType(addr.segment) != SEG_TYPE_LISTS) { - warning("Attempt to use non-list %04x:%04x as list", PRINT_REG(addr)); + error("Attempt to use non-list %04x:%04x as list", PRINT_REG(addr)); return NULL; } ListTable *lt = (ListTable *)_heap[addr.segment]; if (!lt->isValidEntry(addr.offset)) { - warning("Attempt to use non-list %04x:%04x as list", PRINT_REG(addr)); + error("Attempt to use non-list %04x:%04x as list", PRINT_REG(addr)); return NULL; } @@ -567,18 +512,17 @@ Node *SegManager::lookupNode(reg_t addr) { if (addr.isNull()) return NULL; // Non-error null - if (getSegmentType(addr.segment) != SEG_TYPE_NODES) { - // FIXME: This occurs right at the beginning of SQ4, when walking north from the first screen. It doesn't - // seem to have any apparent ill-effects, though, so it's been changed to non-fatal, for now - //error("%s, L%d: Attempt to use non-node %04x:%04x as list node", __FILE__, __LINE__, PRINT_REG(addr)); - warning("Attempt to use non-node %04x:%04x as list node", PRINT_REG(addr)); + SegmentType type = getSegmentType(addr.segment); + + if (type != SEG_TYPE_NODES) { + error("Attempt to use non-node %04x:%04x (type %d) as list node", PRINT_REG(addr), type); return NULL; } NodeTable *nt = (NodeTable *)_heap[addr.segment]; if (!nt->isValidEntry(addr.offset)) { - warning("Attempt to use non-node %04x:%04x as list node", PRINT_REG(addr)); + error("Attempt to use invalid or discarded reference %04x:%04x as list node", PRINT_REG(addr)); return NULL; } @@ -606,7 +550,7 @@ static void *derefPtr(SegManager *segMan, reg_t pointer, int entries, bool wantR if (ret.isRaw != wantRaw) { warning("Dereferencing pointer %04x:%04x (type %d) which is %s, but expected %s", PRINT_REG(pointer), - segMan->_heap[pointer.segment]->getType(), + segMan->getSegmentType(pointer.segment), ret.isRaw ? "raw" : "not raw", wantRaw ? "raw" : "not raw"); } @@ -646,8 +590,12 @@ static inline char getChar(const SegmentRef &ref, uint offset) { reg_t val = ref.reg[offset / 2]; + // segment 0xFFFF means that the scripts are using uninitialized temp-variable space + // we can safely ignore this, if it isn't one of the first 2 chars. + // foreign lsl3 uses kFileIO(readraw) and then immediately uses kReadNumber right at the start if (val.segment != 0) - warning("Attempt to read character from non-raw data"); + if (!((val.segment == 0xFFFF) && (offset > 1))) + warning("Attempt to read character from non-raw data"); return (offset & 1 ? val.offset >> 8 : val.offset & 0xff); } @@ -695,6 +643,14 @@ void SegManager::strncpy(reg_t dest, const char* src, size_t n) { } void SegManager::strncpy(reg_t dest, reg_t src, size_t n) { + if (src.isNull()) { + // Clear target string instead. + if (n > 0) + strcpy(dest, ""); + + return; // empty text + } + SegmentRef dest_r = dereference(dest); const SegmentRef src_r = dereference(src); if (!src_r.isValid()) { @@ -822,6 +778,9 @@ void SegManager::memcpy(byte *dest, reg_t src, size_t n) { } size_t SegManager::strlen(reg_t str) { + if (str.isNull()) + return 0; // empty text + SegmentRef str_r = dereference(str); if (!str_r.isValid()) { warning("Attempt to call strlen on invalid pointer %04x:%04x", PRINT_REG(str)); @@ -841,6 +800,9 @@ size_t SegManager::strlen(reg_t str) { Common::String SegManager::getString(reg_t pointer, int entries) { Common::String ret; + if (pointer.isNull()) + return ret; // empty text + SegmentRef src_r = dereference(pointer); if (!src_r.isValid()) { warning("SegManager::getString(): Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer)); @@ -867,7 +829,6 @@ Common::String SegManager::getString(reg_t pointer, int entries) { return ret; } - byte *SegManager::allocDynmem(int size, const char *descr, reg_t *addr) { SegmentId seg; SegmentObj *mobj = allocSegment(new DynMem(), &seg); @@ -901,14 +862,14 @@ SciArray<reg_t> *SegManager::allocateArray(reg_t *addr) { ArrayTable *table; int offset; - if (!Arrays_seg_id) { - table = (ArrayTable *)allocSegment(new ArrayTable(), &(Arrays_seg_id)); + if (!_arraysSegId) { + table = (ArrayTable *)allocSegment(new ArrayTable(), &(_arraysSegId)); } else - table = (ArrayTable *)_heap[Arrays_seg_id]; + table = (ArrayTable *)_heap[_arraysSegId]; offset = table->allocEntry(); - *addr = make_reg(Arrays_seg_id, offset); + *addr = make_reg(_arraysSegId, offset); return &(table->_table[offset]); } @@ -941,14 +902,14 @@ SciString *SegManager::allocateString(reg_t *addr) { StringTable *table; int offset; - if (!String_seg_id) { - table = (StringTable *)allocSegment(new StringTable(), &(String_seg_id)); + if (!_stringSegId) { + table = (StringTable *)allocSegment(new StringTable(), &(_stringSegId)); } else - table = (StringTable *)_heap[String_seg_id]; + table = (StringTable *)_heap[_stringSegId]; offset = table->allocEntry(); - *addr = make_reg(String_seg_id, offset); + *addr = make_reg(_stringSegId, offset); return &(table->_table[offset]); } @@ -979,4 +940,148 @@ void SegManager::freeString(reg_t addr) { #endif +void SegManager::createClassTable() { + Resource *vocab996 = _resMan->findResource(ResourceId(kResourceTypeVocab, 996), 1); + + if (!vocab996) + error("SegManager: failed to open vocab 996"); + + int totalClasses = vocab996->size >> 2; + _classTable.resize(totalClasses); + + for (uint16 classNr = 0; classNr < totalClasses; classNr++) { + uint16 scriptNr = READ_SCI11ENDIAN_UINT16(vocab996->data + classNr * 4 + 2); + + _classTable[classNr].reg = NULL_REG; + _classTable[classNr].script = scriptNr; + } + + _resMan->unlockResource(vocab996); +} + +reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, reg_t caller) { + if (classnr == 0xffff) + return NULL_REG; + + if (classnr < 0 || (int)_classTable.size() <= classnr || _classTable[classnr].script < 0) { + error("[VM] Attempt to dereference class %x, which doesn't exist (max %x)", classnr, _classTable.size()); + return NULL_REG; + } else { + Class *the_class = &_classTable[classnr]; + if (!the_class->reg.segment) { + getScriptSegment(the_class->script, lock); + + if (!the_class->reg.segment) { + error("[VM] Trying to instantiate class %x by instantiating script 0x%x (%03d) failed;", classnr, the_class->script, the_class->script); + return NULL_REG; + } + } else + if (caller.segment != the_class->reg.segment) + getScript(the_class->reg.segment)->incrementLockers(); + + return the_class->reg; + } +} + +int SegManager::instantiateScript(int scriptNum) { + SegmentId segmentId = getScriptSegment(scriptNum); + Script *scr = getScriptIfLoaded(segmentId); + if (scr) { + if (!scr->isMarkedAsDeleted()) { + scr->incrementLockers(); + return segmentId; + } else { + scr->freeScript(); + } + } else { + scr = allocateScript(scriptNum, &segmentId); + } + + scr->init(scriptNum, _resMan); + scr->load(_resMan); + scr->initialiseLocals(this); + scr->initialiseClasses(this); + + if (getSciVersion() >= SCI_VERSION_1_1) { + scr->initialiseObjectsSci11(this, segmentId); + } else { + scr->initialiseObjectsSci0(this, segmentId); + } + + return segmentId; +} + +void SegManager::uninstantiateScript(int script_nr) { + SegmentId segmentId = getScriptSegment(script_nr); + Script *scr = getScriptIfLoaded(segmentId); + + if (!scr) { // Is it already unloaded? + //warning("unloading script 0x%x requested although not loaded", script_nr); + // This is perfectly valid SCI behaviour + return; + } + + scr->decrementLockers(); // One less locker + + if (scr->getLockers() > 0) + return; + + // Free all classtable references to this script + for (uint i = 0; i < classTableSize(); i++) + if (getClass(i).reg.segment == segmentId) + setClassOffset(i, NULL_REG); + + if (getSciVersion() < SCI_VERSION_1_1) + uninstantiateScriptSci0(script_nr); + // FIXME: Add proper script uninstantiation for SCI 1.1 + + if (!scr->getLockers()) { + // The actual script deletion seems to be done by SCI scripts themselves + scr->markDeleted(); + debugC(kDebugLevelScripts, "Unloaded script 0x%x.", script_nr); + } +} + +void SegManager::uninstantiateScriptSci0(int script_nr) { + bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); + SegmentId segmentId = getScriptSegment(script_nr); + Script *scr = getScript(segmentId); + reg_t reg = make_reg(segmentId, oldScriptHeader ? 2 : 0); + int objType, objLength = 0; + + // Make a pass over the object in order uninstantiate all superclasses + + do { + reg.offset += objLength; // Step over the last checked object + + objType = READ_SCI11ENDIAN_UINT16(scr->getBuf(reg.offset)); + if (!objType) + break; + objLength = READ_SCI11ENDIAN_UINT16(scr->getBuf(reg.offset + 2)); + + reg.offset += 4; // Step over header + + if ((objType == SCI_OBJ_OBJECT) || (objType == SCI_OBJ_CLASS)) { // object or class? + reg.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET) + int16 superclass = READ_SCI11ENDIAN_UINT16(scr->getBuf(reg.offset + 2)); + + if (superclass >= 0) { + int superclass_script = getClass(superclass).script; + + if (superclass_script == script_nr) { + if (scr->getLockers()) + scr->decrementLockers(); // Decrease lockers if this is us ourselves + } else + uninstantiateScript(superclass_script); + // Recurse to assure that the superclass lockers number gets decreased + } + + reg.offset += SCRIPT_OBJECT_MAGIC_OFFSET; + } // if object or class + + reg.offset -= 4; // Step back on header + + } while (objType != 0); +} + } // End of namespace Sci diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 9312f51f9d..a7f5f8517f 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -28,7 +28,9 @@ #include "common/scummsys.h" #include "common/serializer.h" +#include "sci/engine/script.h" #include "sci/engine/vm.h" +#include "sci/engine/vm_types.h" #include "sci/engine/segment.h" namespace Sci { @@ -42,8 +44,6 @@ namespace Sci { error("%s, line, %d, %s", __FILE__, __LINE__, msg); \ } - - /** * Parameters for getScriptSegment(). */ @@ -53,6 +53,7 @@ enum ScriptLoadType { SCRIPT_GET_LOCK = 3 /**< Load, if neccessary, and lock */ }; +class Script; class SegManager : public Common::Serializable { friend class Console; @@ -96,6 +97,11 @@ public: void reconstructScripts(EngineState *s); /** + * Reconstructs the stack. Used when restoring saved games + */ + void reconstructStack(EngineState *s); + + /** * Determines the segment occupied by a certain script, if any. * @param script_nr Number of the script to look up * @return The script's segment ID, or 0 on failure @@ -111,6 +117,30 @@ public: */ SegmentId getScriptSegment(int script_nr, ScriptLoadType load); + /** + * Makes sure that a script and its superclasses get loaded to the heap. + * If the script already has been loaded, only the number of lockers is + * increased. All scripts containing superclasses of this script are loaded + * recursively as well, unless 'recursive' is set to zero. The + * complementary function is "uninstantiateScript()" below. + * @param[in] script_nr The script number to load + * @return The script's segment ID or 0 if out of heap + */ + int instantiateScript(int script_nr); + + /** + * Decreases the numer of lockers of a script and unloads it if that number + * reaches zero. + * This function will recursively unload scripts containing its + * superclasses, if those aren't locked by other scripts as well. + * @param[in] script_nr The script number that is requestet to be unloaded + */ + void uninstantiateScript(int script_nr); + +private: + void uninstantiateScriptSci0(int script_nr); + +public: // TODO: document this reg_t getClassAddress(int classnr, ScriptLoadType lock, reg_t caller); @@ -131,28 +161,7 @@ public: * @param seg ID of the script segment to check for * @return A pointer to the Script object, or NULL */ - Script *getScriptIfLoaded(SegmentId seg); - - - // 1b. Script Initialisation - - // The set of functions below are intended - // to be used during script instantiation, - // i.e. loading and linking. - - /** - * Initializes a script's local variable block - * All variables are initialized to zero. - * @param seg Segment containing the script to initialize - * @param nr Number of local variables to allocate - */ - void scriptInitialiseLocalsZero(SegmentId seg, int nr); - - /** - * Initializes a script's local variable block according to a prototype - * @param location Location to initialize from - */ - void scriptInitialiseLocals(reg_t location); + Script *getScriptIfLoaded(SegmentId seg) const; // 2. Clones @@ -378,39 +387,39 @@ public: * @param type The type of the segment to find * @return The segment number, or -1 if the segment wasn't found */ - SegmentId findSegmentByType(int type); + SegmentId findSegmentByType(int type) const; // TODO: document this - SegmentObj *getSegmentObj(SegmentId seg); + SegmentObj *getSegmentObj(SegmentId seg) const; // TODO: document this - SegmentType getSegmentType(SegmentId seg); + SegmentType getSegmentType(SegmentId seg) const; // TODO: document this - SegmentObj *getSegment(SegmentId seg, SegmentType type); + SegmentObj *getSegment(SegmentId seg, SegmentType type) const; /** * Retrieves an object from the specified location * @param[in] offset Location (segment, offset) of the object * @return The object in question, or NULL if there is none */ - Object *getObject(reg_t pos); + Object *getObject(reg_t pos) const; /** * Checks whether a heap address contains an object * @parm obj The address to check * @return True if it is an object, false otherwise */ - bool isObject(reg_t obj) { return getObject(obj) != NULL; } + bool isObject(reg_t obj) const { return getObject(obj) != NULL; } // TODO: document this - bool isHeapObject(reg_t pos); + bool isHeapObject(reg_t pos) const; /** * Determines the name of an object * @param[in] pos Location (segment, offset) of the object * @return A name for that object, or a string describing an error - * that occured while looking it up. The string is stored + * that occurred while looking it up. The string is stored * in a static buffer and need not be freed (neither may * it be modified). */ @@ -429,22 +438,27 @@ public: */ reg_t findObjectByName(const Common::String &name, int index = -1); - void scriptInitialiseObjectsSci11(SegmentId seg); - - uint32 classTableSize() { return _classTable.size(); } - Class getClass(int index) { return _classTable[index]; } + uint32 classTableSize() const { return _classTable.size(); } + Class getClass(int index) const { return _classTable[index]; } void setClassOffset(int index, reg_t offset) { _classTable[index].reg = offset; } void resizeClassTable(uint32 size) { _classTable.resize(size); } /** * Obtains the system strings segment ID */ - SegmentId getSysStringsSegment() { return sysStringsSegment; } + SegmentId getSysStringsSegment() { return _sysStringsSegId; } -public: // TODO: make private - Common::Array<SegmentObj *> _heap; - // Only accessible from saveLoadWithSerializer() - Common::Array<Class> _classTable; /**< Table of all classes */ + /** + * Get a pointer to the system string with the specified index, + * or NULL if that index is invalid. + * + * This method is currently only used by kString(). + */ + SystemString *getSystemString(uint idx) const { + if (idx >= SYS_STRINGS_MAX) + return NULL; + return &_sysStrings->_strings[idx]; + } #ifdef ENABLE_SCI32 SciArray<reg_t> *allocateArray(reg_t *addr); @@ -453,35 +467,35 @@ public: // TODO: make private SciString *allocateString(reg_t *addr); SciString *lookupString(reg_t addr); void freeString(reg_t addr); - SegmentId getStringSegmentId() { return String_seg_id; } + SegmentId getStringSegmentId() { return _stringSegId; } #endif + const Common::Array<SegmentObj *> &getSegments() const { return _heap; } + private: + Common::Array<SegmentObj *> _heap; + Common::Array<Class> _classTable; /**< Table of all classes */ /** Map script ids to segment ids. */ Common::HashMap<int, SegmentId> _scriptSegMap; ResourceManager *_resMan; - SegmentId Clones_seg_id; ///< ID of the (a) clones segment - SegmentId Lists_seg_id; ///< ID of the (a) list segment - SegmentId Nodes_seg_id; ///< ID of the (a) node segment - SegmentId Hunks_seg_id; ///< ID of the (a) hunk segment + SegmentId _clonesSegId; ///< ID of the (a) clones segment + SegmentId _listsSegId; ///< ID of the (a) list segment + SegmentId _nodesSegId; ///< ID of the (a) node segment + SegmentId _hunksSegId; ///< ID of the (a) hunk segment /* System strings */ - SegmentId sysStringsSegment; -public: // TODO: make private. Only kString() needs direct access - SystemStrings *sysStrings; - -private: + SegmentId _sysStringsSegId; + SystemStrings *_sysStrings; #ifdef ENABLE_SCI32 - SegmentId Arrays_seg_id; - SegmentId String_seg_id; + SegmentId _arraysSegId; + SegmentId _stringSegId; #endif private: SegmentObj *allocSegment(SegmentObj *mem, SegmentId *segid); - LocalVariables *allocLocalsSegment(Script *scr, int count); int deallocate(SegmentId seg, bool recursive); void createClassTable(); @@ -494,6 +508,9 @@ private: * 'seg' is a valid segment */ bool check(SegmentId seg); + +public: + LocalVariables *allocLocalsSegment(Script *scr); }; } // End of namespace Sci diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 0e0a759d4b..cb908979a3 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -86,175 +86,52 @@ SegmentObj *SegmentObj::createSegmentObj(SegmentType type) { return mem; } -Script::Script() : SegmentObj(SEG_TYPE_SCRIPT) { - _nr = 0; - _buf = NULL; - _bufSize = 0; - _scriptSize = 0; - _heapSize = 0; - - _synonyms = NULL; - _heapStart = NULL; - _exportTable = NULL; - - _localsOffset = 0; - _localsSegment = 0; - _localsBlock = NULL; - - _markedAsDeleted = false; -} - -Script::~Script() { - freeScript(); -} - -void Script::freeScript() { - free(_buf); - _buf = NULL; - _bufSize = 0; - - _objects.clear(); - _codeBlocks.clear(); -} - -void Script::init(int script_nr, ResourceManager *resMan) { - Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0); - - _localsOffset = 0; - _localsBlock = NULL; - - _codeBlocks.clear(); - - _markedAsDeleted = false; - - _nr = script_nr; - _buf = 0; - _heapStart = 0; - - _scriptSize = script->size; - _bufSize = script->size; - _heapSize = 0; - - _lockers = 1; - - if (getSciVersion() == SCI_VERSION_0_EARLY) { - _bufSize += READ_LE_UINT16(script->data) * 2; - } else if (getSciVersion() >= SCI_VERSION_1_1) { - /** - * In SCI11, the heap was in a separate space from the script. - * We append it to the end of the script, and adjust addressing accordingly. - * However, since we address the heap with a 16-bit pointer, the combined - * size of the stack and the heap must be 64KB. So far this has worked - * for SCI11, SCI2 and SCI21 games. SCI3 games use a different script format, - * and theoretically they can exceed the 64KB boundary using relocation. - */ - Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, script_nr), 0); - _bufSize += heap->size; - _heapSize = heap->size; - - // Ensure that the start of the heap resource can be word-aligned. - if (script->size & 2) { - _bufSize++; - _scriptSize++; - } - - // As mentioned above, the script and the heap together should not exceed 64KB - if (_bufSize > 65535) - error("Script and heap sizes combined exceed 64K. This means a fundamental " - "design bug was made regarding SCI1.1 and newer games.\nPlease " - "report this error to the ScummVM team"); - } -} - -void Script::load(ResourceManager *resMan) { - Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, _nr), 0); - assert(script != 0); - - _buf = (byte *)malloc(_bufSize); - assert(_buf); - - assert(_bufSize >= script->size); - memcpy(_buf, script->data, script->size); - - if (getSciVersion() >= SCI_VERSION_1_1) { - Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, _nr), 0); - assert(heap != 0); - - _heapStart = _buf + _scriptSize; - - assert(_bufSize - _scriptSize <= heap->size); - memcpy(_heapStart, heap->data, heap->size); - } - - _codeBlocks.clear(); - - _exportTable = 0; - _numExports = 0; - _synonyms = 0; - _numSynonyms = 0; - - if (getSciVersion() >= SCI_VERSION_1_1) { - if (READ_LE_UINT16(_buf + 1 + 5) > 0) { - _exportTable = (const uint16 *)(_buf + 1 + 5 + 2); - _numExports = READ_SCI11ENDIAN_UINT16(_exportTable - 1); - } - } else { - _exportTable = (const uint16 *)findBlock(SCI_OBJ_EXPORTS); - if (_exportTable) { - _numExports = READ_SCI11ENDIAN_UINT16(_exportTable + 1); - _exportTable += 3; // skip header plus 2 bytes (_exportTable is a uint16 pointer) - } - _synonyms = findBlock(SCI_OBJ_SYNONYMS); - if (_synonyms) { - _numSynonyms = READ_SCI11ENDIAN_UINT16(_synonyms + 2) / 4; - _synonyms += 4; // skip header - } +const char *SegmentObj::getSegmentTypeName(SegmentType type) { + switch (type) { + case SEG_TYPE_SCRIPT: + return "script"; + break; + case SEG_TYPE_CLONES: + return "clones"; + break; + case SEG_TYPE_LOCALS: + return "locals"; + break; + case SEG_TYPE_SYS_STRINGS: + return "strings"; + break; + case SEG_TYPE_STACK: + return "stack"; + break; + case SEG_TYPE_HUNK: + return "hunk"; + break; + case SEG_TYPE_LISTS: + return "lists"; + break; + case SEG_TYPE_NODES: + return "nodes"; + break; + case SEG_TYPE_DYNMEM: + return "dynmem"; + break; +#ifdef ENABLE_SCI32 + case SEG_TYPE_ARRAY: + return "array"; + break; + case SEG_TYPE_STRING: + return "string"; + break; +#endif + default: + error("Unknown SegmentObj type %d", type); + break; } -} - -Object *Script::allocateObject(uint16 offset) { - return &_objects[offset]; -} - -Object *Script::getObject(uint16 offset) { - if (_objects.contains(offset)) - return &_objects[offset]; - else - return 0; -} - -const Object *Script::getObject(uint16 offset) const { - if (_objects.contains(offset)) - return &_objects[offset]; - else - return 0; -} - -Object *Script::scriptObjInit(reg_t obj_pos, bool fullObjectInit) { - Object *obj; - - if (getSciVersion() < SCI_VERSION_1_1 && fullObjectInit) - obj_pos.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET) - - VERIFY(obj_pos.offset < _bufSize, "Attempt to initialize object beyond end of script\n"); - - obj = allocateObject(obj_pos.offset); - - VERIFY(obj_pos.offset + kOffsetFunctionArea < (int)_bufSize, "Function area pointer stored beyond end of script\n"); - - obj->init(_buf, obj_pos, fullObjectInit); - - return obj; -} - -void Script::scriptObjRemove(reg_t obj_pos) { - if (getSciVersion() < SCI_VERSION_1_1) - obj_pos.offset += 8; - - _objects.erase(obj_pos.toUint16()); + return NULL; } // This helper function is used by Script::relocateLocal and Object::relocate +// Duplicate in segment.cpp and script.cpp static bool relocateBlock(Common::Array<reg_t> &block, int block_location, SegmentId segment, int location, size_t scriptSize) { int rel = location - block_location; @@ -267,7 +144,7 @@ static bool relocateBlock(Common::Array<reg_t> &block, int block_location, Segme return false; if (rel & 1) { - warning("Attempt to relocate odd variable #%d.5e (relative to %04x)\n", idx, block_location); + error("Attempt to relocate odd variable #%d.5e (relative to %04x)\n", idx, block_location); return false; } block[idx].segment = segment; // Perform relocation @@ -277,182 +154,12 @@ static bool relocateBlock(Common::Array<reg_t> &block, int block_location, Segme return true; } -bool Script::relocateLocal(SegmentId segment, int location) { - if (_localsBlock) - return relocateBlock(_localsBlock->_locals, _localsOffset, segment, location, _scriptSize); - else - return false; -} - -void Script::scriptAddCodeBlock(reg_t location) { - CodeBlock cb; - cb.pos = location; - cb.size = READ_SCI11ENDIAN_UINT16(_buf + location.offset - 2); - _codeBlocks.push_back(cb); -} - -void Script::relocate(reg_t block) { - byte *heap = _buf; - uint16 heapSize = (uint16)_bufSize; - uint16 heapOffset = 0; - - if (getSciVersion() >= SCI_VERSION_1_1) { - heap = _heapStart; - heapSize = (uint16)_heapSize; - heapOffset = _scriptSize; - } - - VERIFY(block.offset < (uint16)heapSize && READ_SCI11ENDIAN_UINT16(heap + block.offset) * 2 + block.offset < (uint16)heapSize, - "Relocation block outside of script\n"); - - int count = READ_SCI11ENDIAN_UINT16(heap + block.offset); - int exportIndex = 0; - - for (int i = 0; i < count; i++) { - int pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset; - // This occurs in SCI01/SCI1 games where every usually one export - // value is zero. It seems that in this situation, we should skip - // the export and move to the next one, though the total count - // of valid exports remains the same - if (!pos) { - exportIndex++; - pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset; - if (!pos) - error("Script::relocate(): Consecutive zero exports found"); - } - - if (!relocateLocal(block.segment, pos)) { - bool done = false; - uint k; - - ObjMap::iterator it; - const ObjMap::iterator end = _objects.end(); - for (it = _objects.begin(); !done && it != end; ++it) { - if (it->_value.relocate(block.segment, pos, _scriptSize)) - done = true; - } - - // Sanity check for SCI0-SCI1 - if (getSciVersion() < SCI_VERSION_1_1) { - for (k = 0; !done && k < _codeBlocks.size(); k++) { - if (pos >= _codeBlocks[k].pos.offset && - pos < _codeBlocks[k].pos.offset + _codeBlocks[k].size) - done = true; - } - } - - if (!done) { - debug("While processing relocation block %04x:%04x:\n", PRINT_REG(block)); - debug("Relocation failed for index %04x (%d/%d)\n", pos, exportIndex + 1, count); - if (_localsBlock) - debug("- locals: %d at %04x\n", _localsBlock->_locals.size(), _localsOffset); - else - debug("- No locals\n"); - for (it = _objects.begin(), k = 0; it != end; ++it, ++k) - debug("- obj#%d at %04x w/ %d vars\n", k, it->_value.getPos().offset, it->_value.getVarCount()); - debug("Trying to continue anyway...\n"); - } - } - - exportIndex++; - } -} - -void Script::incrementLockers() { - _lockers++; -} - -void Script::decrementLockers() { - if (_lockers > 0) - _lockers--; -} - -int Script::getLockers() const { - return _lockers; -} - -void Script::setLockers(int lockers) { - _lockers = lockers; -} - -uint16 Script::validateExportFunc(int pubfunct) { - bool exportsAreWide = (g_sci->_features->detectLofsType() == SCI_VERSION_1_MIDDLE); - - if (_numExports <= pubfunct) { - warning("validateExportFunc(): pubfunct is invalid"); - return 0; - } - - if (exportsAreWide) - pubfunct *= 2; - uint16 offset = READ_SCI11ENDIAN_UINT16(_exportTable + pubfunct); - VERIFY(offset < _bufSize, "invalid export function pointer"); - - return offset; -} - -byte *Script::findBlock(int type) { - byte *buf = _buf; - bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); - - if (oldScriptHeader) - buf += 2; - - do { - int seekerType = READ_LE_UINT16(buf); - - if (seekerType == 0) - break; - if (seekerType == type) - return buf; - - int seekerSize = READ_LE_UINT16(buf + 2); - assert(seekerSize > 0); - buf += seekerSize; - } while (1); - - return NULL; -} - - -// memory operations - -void Script::mcpyInOut(int dst, const void *src, size_t n) { - if (_buf) { - assert(dst + n <= _bufSize); - memcpy(_buf + dst, src, n); - } -} - -int16 Script::getHeap(uint16 offset) const { - assert(offset + 1 < (int)_bufSize); - return READ_SCI11ENDIAN_UINT16(_buf + offset); -// return (_buf[offset] | (_buf[offset+1]) << 8); -} - SegmentRef SegmentObj::dereference(reg_t pointer) { error("Error: Trying to dereference pointer %04x:%04x to inappropriate segment", PRINT_REG(pointer)); return SegmentRef(); } -bool Script::isValidOffset(uint16 offset) const { - return offset < _bufSize; -} - -SegmentRef Script::dereference(reg_t pointer) { - if (pointer.offset > _bufSize) { - warning("Script::dereference(): Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)", - PRINT_REG(pointer), (uint)_bufSize); - return SegmentRef(); - } - - SegmentRef ret; - ret.isRaw = true; - ret.maxSize = _bufSize - pointer.offset; - ret.raw = _buf + pointer.offset; - return ret; -} bool LocalVariables::isValidOffset(uint16 offset) const { return offset < _locals.size() * 2; @@ -471,7 +178,16 @@ SegmentRef LocalVariables::dereference(reg_t pointer) { if (ret.maxSize > 0) { ret.reg = &_locals[pointer.offset / 2]; } else { - warning("LocalVariables::dereference: Offset at end or out of bounds %04x:%04x", PRINT_REG(pointer)); + if ((g_sci->getEngineState()->currentRoomNumber() == 660 || g_sci->getEngineState()->currentRoomNumber() == 660) + && g_sci->getGameId() == GID_LAURABOW2) { + // Happens in two places during the intro of LB2CD, both from kMemory(peek): + // - room 160: Heap 160 has 83 local variables (0-82), and the game + // asks for variables at indices 83 - 90 too. + // - room 220: Heap 220 has 114 local variables (0-113), and the + // game asks for variables at indices 114-120 too. + } else { + error("LocalVariables::dereference: Offset at end or out of bounds %04x:%04x", PRINT_REG(pointer)); + } ret.reg = 0; } return ret; @@ -518,58 +234,21 @@ SegmentRef SystemStrings::dereference(reg_t pointer) { if (isValidOffset(pointer.offset)) ret.raw = (byte *)(_strings[pointer.offset]._value); else { - // This occurs in KQ5CD when interacting with certain objects - warning("SystemStrings::dereference(): Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer)); - } - - return ret; -} - - -//-------------------- script -------------------- -reg_t Script::findCanonicAddress(SegManager *segMan, reg_t addr) const { - addr.offset = 0; - return addr; -} - -void Script::freeAtAddress(SegManager *segMan, reg_t addr) { - /* - debugC(2, kDebugLevelGC, "[GC] Freeing script %04x:%04x", PRINT_REG(addr)); - if (_localsSegment) - debugC(2, kDebugLevelGC, "[GC] Freeing locals %04x:0000", _localsSegment); - */ - - if (_markedAsDeleted) - segMan->deallocateScript(_nr); -} - -void Script::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const { - (*note)(param, make_reg(segId, 0)); -} - -void Script::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { - if (addr.offset <= _bufSize && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(_buf + addr.offset)) { - const Object *obj = getObject(addr.offset); - if (obj) { - // Note all local variables, if we have a local variable environment - if (_localsSegment) - (*note)(param, make_reg(_localsSegment, 0)); - - for (uint i = 0; i < obj->getVarCount(); i++) - (*note)(param, obj->getVariable(i)); + if (g_sci->getGameId() == GID_KQ5) { + // This occurs in KQ5CD when interacting with certain objects } else { - warning("Request for outgoing script-object reference at %04x:%04x failed", PRINT_REG(addr)); + error("SystemStrings::dereference(): Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer)); } - } else { - /* warning("Unexpected request for outgoing script-object references at %04x:%04x", PRINT_REG(addr));*/ - /* Happens e.g. when we're looking into strings */ } + + return ret; } //-------------------- clones -------------------- -void CloneTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { +Common::Array<reg_t> CloneTable::listAllOutgoingReferences(reg_t addr) const { + Common::Array<reg_t> tmp; // assert(addr.segment == _segId); if (!isValidEntry(addr.offset)) { @@ -580,20 +259,20 @@ void CloneTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback // Emit all member variables (including references to the 'super' delegate) for (uint i = 0; i < clone->getVarCount(); i++) - (*note)(param, clone->getVariable(i)); + tmp.push_back(clone->getVariable(i)); // Note that this also includes the 'base' object, which is part of the script and therefore also emits the locals. - (*note)(param, clone->getPos()); + tmp.push_back(clone->getPos()); //debugC(2, kDebugLevelGC, "[GC] Reporting clone-pos %04x:%04x", PRINT_REG(clone->pos)); + + return tmp; } void CloneTable::freeAtAddress(SegManager *segMan, reg_t addr) { #ifdef GC_DEBUG - Object *victim_obj; - -// assert(addr.segment == _segId); + // assert(addr.segment == _segId); - victim_obj = &(_table[addr.offset]); + Object *victim_obj = &(_table[addr.offset]); if (!(victim_obj->_flags & OBJECT_FLAG_FREED)) warning("[GC] Clone %04x:%04x not reachable and not freed (freeing now)", PRINT_REG(addr)); @@ -620,11 +299,14 @@ reg_t LocalVariables::findCanonicAddress(SegManager *segMan, reg_t addr) const { return make_reg(owner_seg, 0); } -void LocalVariables::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { +Common::Array<reg_t> LocalVariables::listAllOutgoingReferences(reg_t addr) const { + Common::Array<reg_t> tmp; // assert(addr.segment == _segId); for (uint i = 0; i < _locals.size(); i++) - (*note)(param, _locals[i]); + tmp.push_back(_locals[i]); + + return tmp; } @@ -634,11 +316,14 @@ reg_t DataStack::findCanonicAddress(SegManager *segMan, reg_t addr) const { return addr; } -void DataStack::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { +Common::Array<reg_t> DataStack::listAllOutgoingReferences(reg_t object) const { + Common::Array<reg_t> tmp; fprintf(stderr, "Emitting %d stack entries\n", _capacity); for (int i = 0; i < _capacity; i++) - (*note)(param, _entries[i]); + tmp.push_back(_entries[i]); fprintf(stderr, "DONE"); + + return tmp; } @@ -647,18 +332,20 @@ void ListTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) { freeEntry(sub_addr.offset); } -void ListTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { +Common::Array<reg_t> ListTable::listAllOutgoingReferences(reg_t addr) const { + Common::Array<reg_t> tmp; if (!isValidEntry(addr.offset)) { - warning("Invalid list referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); - return; + error("Invalid list referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); } const List *list = &(_table[addr.offset]); - note(param, list->first); - note(param, list->last); + tmp.push_back(list->first); + tmp.push_back(list->last); // We could probably get away with just one of them, but // let's be conservative here. + + return tmp; } @@ -667,19 +354,21 @@ void NodeTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) { freeEntry(sub_addr.offset); } -void NodeTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { +Common::Array<reg_t> NodeTable::listAllOutgoingReferences(reg_t addr) const { + Common::Array<reg_t> tmp; if (!isValidEntry(addr.offset)) { - warning("Invalid node referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); - return; + error("Invalid node referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); } const Node *node = &(_table[addr.offset]); // We need all four here. Can't just stick with 'pred' OR 'succ' because node operations allow us // to walk around from any given node - note(param, node->pred); - note(param, node->succ); - note(param, node->key); - note(param, node->value); + tmp.push_back(node->pred); + tmp.push_back(node->succ); + tmp.push_back(node->key); + tmp.push_back(node->value); + + return tmp; } @@ -743,7 +432,7 @@ int Object::propertyOffsetToId(SegManager *segMan, int propertyOffset) const { int selectors = getVarCount(); if (propertyOffset < 0 || (propertyOffset >> 1) >= selectors) { - warning("Applied propertyOffsetToId to invalid property offset %x (property #%d not in [0..%d])", + error("Applied propertyOffsetToId to invalid property offset %x (property #%d not in [0..%d])", propertyOffset, propertyOffset >> 1, selectors - 1); return -1; } @@ -800,8 +489,9 @@ reg_t DynMem::findCanonicAddress(SegManager *segMan, reg_t addr) const { return addr; } -void DynMem::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const { - (*note)(param, make_reg(segId, 0)); +Common::Array<reg_t> DynMem::listAllDeallocatable(SegmentId segId) const { + const reg_t r = make_reg(segId, 0); + return Common::Array<reg_t>(&r, 1); } #ifdef ENABLE_SCI32 @@ -819,10 +509,10 @@ void ArrayTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) { freeEntry(sub_addr.offset); } -void ArrayTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { +Common::Array<reg_t> ArrayTable::listAllOutgoingReferences(reg_t addr) const { + Common::Array<reg_t> tmp; if (!isValidEntry(addr.offset)) { - warning("Invalid array referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); - return; + error("Invalid array referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); } const SciArray<reg_t> *array = &(_table[addr.offset]); @@ -830,8 +520,10 @@ void ArrayTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback for (uint32 i = 0; i < array->getSize(); i++) { reg_t value = array->getValue(i); if (value.segment != 0) - note(param, value); + tmp.push_back(value); } + + return tmp; } Common::String SciString::toString() const { diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index f1b6dccaa2..2465576302 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -67,7 +67,7 @@ enum SegmentType { SEG_TYPE_NODES = 7, SEG_TYPE_HUNK = 8, SEG_TYPE_DYNMEM = 9, - SEG_TYPE_STRING_FRAG = 10, // obsolete, we keep it to be able to load old saves + // 10 used to be string fragments, now obsolete #ifdef ENABLE_SCI32 SEG_TYPE_ARRAY = 11, @@ -80,10 +80,9 @@ enum SegmentType { struct SegmentObj : public Common::Serializable { SegmentType _type; - typedef void (*NoteCallback)(void *param, reg_t addr); // FIXME: Bad choice of name - public: static SegmentObj *createSegmentObj(SegmentType type); + static const char *getSegmentTypeName(SegmentType type); public: SegmentObj(SegmentType type) : _type(type) {} @@ -106,6 +105,7 @@ public: /** * Finds the canonic address associated with sub_reg. + * Used by the garbage collector. * * For each valid address a, there exists a canonic address c(a) such that c(a) = c(c(a)). * This address "governs" a in the sense that deallocating c(a) will deallocate a. @@ -116,25 +116,31 @@ public: /** * Deallocates all memory associated with the specified address. + * Used by the garbage collector. * @param sub_addr address (within the given segment) to deallocate */ virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) {} /** - * Iterates over and reports all addresses within the current segment. - * @param note Invoked for each address on which free_at_address() makes sense - * @param param parameter passed to 'note' + * Iterates over and reports all addresses within the segment. + * Used by the garbage collector. + * @return a list of addresses within the segment */ - virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const {} + virtual Common::Array<reg_t> listAllDeallocatable(SegmentId segId) const { + return Common::Array<reg_t>(); + } /** * Iterates over all references reachable from the specified object. - * @param object object (within the current segment) to analyse - * @param param parameter passed to 'note' - * @param note Invoked for each outgoing reference within the object - * Note: This function may also choose to report numbers (segment 0) as adresses + * Used by the garbage collector. + * @param object object (within the current segment) to analyse + * @return a list of outgoing references within the object + * + * @note This function may also choose to report numbers (segment 0) as adresses */ - virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const {} + virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const { + return Common::Array<reg_t>(); + } }; @@ -195,7 +201,7 @@ public: virtual bool isValidOffset(uint16 offset) const; virtual SegmentRef dereference(reg_t pointer); virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const; - virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const; + virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const; virtual void saveLoadWithSerializer(Common::Serializer &ser); }; @@ -331,199 +337,6 @@ private: reg_t _pos; /**< Object offset within its script; for clones, this is their base */ }; -struct CodeBlock { - reg_t pos; - int size; -}; - -typedef Common::HashMap<uint16, Object> ObjMap; - -class Script : public SegmentObj { -public: - int _nr; /**< Script number */ - byte *_buf; /**< Static data buffer, or NULL if not used */ - byte *_heapStart; /**< Start of heap if SCI1.1, NULL otherwise */ - - uint32 getScriptSize() { return _scriptSize; } - uint32 getHeapSize() { return _heapSize; } - uint32 getBufSize() { return _bufSize; } - -protected: - int _lockers; /**< Number of classes and objects that require this script */ - -private: - size_t _scriptSize; - size_t _heapSize; - size_t _bufSize; - - const uint16 *_exportTable; /**< Abs. offset of the export table or 0 if not present */ - uint16 _numExports; /**< Number of entries in the exports table */ - - const byte *_synonyms; /**< Synonyms block or 0 if not present*/ - uint16 _numSynonyms; /**< Number of entries in the synonyms block */ - - Common::Array<CodeBlock> _codeBlocks; - -public: - /** - * Table for objects, contains property variables. - * Indexed by the TODO offset. - */ - ObjMap _objects; - - int _localsOffset; - SegmentId _localsSegment; /**< The local variable segment */ - LocalVariables *_localsBlock; - - bool _markedAsDeleted; - -public: - Script(); - ~Script(); - - void freeScript(); - void init(int script_nr, ResourceManager *resMan); - void load(ResourceManager *resMan); - - virtual bool isValidOffset(uint16 offset) const; - virtual SegmentRef dereference(reg_t pointer); - virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const; - virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr); - virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const; - virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const; - - virtual void saveLoadWithSerializer(Common::Serializer &ser); - - Object *allocateObject(uint16 offset); - Object *getObject(uint16 offset); - const Object *getObject(uint16 offset) const; - - /** - * Informs the segment manager that a code block must be relocated - * @param location Start of block to relocate - */ - void scriptAddCodeBlock(reg_t location); - - /** - * Initializes an object within the segment manager - * @param obj_pos Location (segment, offset) of the object. It must - * point to the beginning of the script/class block - * (as opposed to what the VM considers to be the - * object location) - * @returns A newly created Object describing the object, - * stored within the relevant script - */ - Object *scriptObjInit(reg_t obj_pos, bool fullObjectInit = true); - - /** - * Removes a script object - * @param obj_pos Location (segment, offset) of the object. - */ - void scriptObjRemove(reg_t obj_pos); - - /** - * Processes a relocation block witin a script - * This function is idempotent, but it must only be called after all - * objects have been instantiated, or a run-time error will occur. - * @param obj_pos Location (segment, offset) of the block - * @return Location of the relocation block - */ - void relocate(reg_t block); - -private: - bool relocateLocal(SegmentId segment, int location); - -public: - // script lock operations - - /** Increments the number of lockers of this script by one. */ - void incrementLockers(); - - /** Decrements the number of lockers of this script by one. */ - void decrementLockers(); - - /** - * Retrieves the number of locks held on this script. - * @return the number of locks held on the previously identified script - */ - int getLockers() const; - - /** Sets the number of locks held on this script. */ - void setLockers(int lockers); - - /** - * Retrieves a pointer to the exports of this script - * @return pointer to the exports. - */ - const uint16 *getExportTable() const { return _exportTable; } - - /** - * Retrieves the number of exports of script. - * @return the number of exports of this script - */ - uint16 getExportsNr() const { return _numExports; } - - /** - * Retrieves a pointer to the synonyms associated with this script - * @return pointer to the synonyms, in non-parsed format. - */ - const byte *getSynonyms() const { return _synonyms; } - - /** - * Retrieves the number of synonyms associated with this script. - * @return the number of synonyms associated with this script - */ - uint16 getSynonymsNr() const { return _numSynonyms; } - - /** - * Validate whether the specified public function is exported by - * the script in the specified segment. - * @param pubfunct Index of the function to validate - * @return NULL if the public function is invalid, its - * offset into the script's segment otherwise - */ - uint16 validateExportFunc(int pubfunct); - - /** - * Marks the script as deleted. - * This will not actually delete the script. If references remain present on the - * heap or the stack, the script will stay in memory in a quasi-deleted state until - * either unreachable (resulting in its eventual deletion) or reloaded (resulting - * in its data being updated). - */ - void markDeleted() { - _markedAsDeleted = true; - } - - /** - * Determines whether the script is marked as being deleted. - */ - bool isMarkedAsDeleted() const { - return _markedAsDeleted; - } - - /** - * Copies a byte string into a script's heap representation. - * @param dst script-relative offset of the destination area - * @param src pointer to the data source location - * @param n number of bytes to copy - */ - void mcpyInOut(int dst, const void *src, size_t n); - - - /** - * Retrieves a 16 bit value from within a script's heap representation. - * @param offset offset to read from - * @return the value read from the specified location - */ - int16 getHeap(uint16 offset) const; - - /** - * Finds the pointer where a block of a specific type starts from - */ - byte *findBlock(int type); -}; - /** Data stack */ struct DataStack : SegmentObj { int _capacity; /**< Number of stack entries */ @@ -542,7 +355,7 @@ public: virtual bool isValidOffset(uint16 offset) const; virtual SegmentRef dereference(reg_t pointer); virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const; - virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const; + virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const; virtual void saveLoadWithSerializer(Common::Serializer &ser); }; @@ -630,10 +443,12 @@ public: entries_used--; } - virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const { + virtual Common::Array<reg_t> listAllDeallocatable(SegmentId segId) const { + Common::Array<reg_t> tmp; for (uint i = 0; i < _table.size(); i++) if (isValidEntry(i)) - (*note)(param, make_reg(segId, i)); + tmp.push_back(make_reg(segId, i)); + return tmp; } }; @@ -643,7 +458,7 @@ struct CloneTable : public Table<Clone> { CloneTable() : Table<Clone>(SEG_TYPE_CLONES) {} virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr); - virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const; + virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const; virtual void saveLoadWithSerializer(Common::Serializer &ser); }; @@ -654,7 +469,7 @@ struct NodeTable : public Table<Node> { NodeTable() : Table<Node>(SEG_TYPE_NODES) {} virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr); - virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const; + virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const; virtual void saveLoadWithSerializer(Common::Serializer &ser); }; @@ -665,7 +480,7 @@ struct ListTable : public Table<List> { ListTable() : Table<List>(SEG_TYPE_LISTS) {} virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr); - virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const; + virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const; virtual void saveLoadWithSerializer(Common::Serializer &ser); }; @@ -678,7 +493,10 @@ struct HunkTable : public Table<Hunk> { virtual void freeEntry(int idx) { Table<Hunk>::freeEntry(idx); + if (!_table[idx].mem) + warning("Attempt to free an already freed hunk"); free(_table[idx].mem); + _table[idx].mem = 0; } virtual void saveLoadWithSerializer(Common::Serializer &ser); @@ -701,7 +519,7 @@ public: virtual bool isValidOffset(uint16 offset) const; virtual SegmentRef dereference(reg_t pointer); virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const; - virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const; + virtual Common::Array<reg_t> listAllDeallocatable(SegmentId segId) const; virtual void saveLoadWithSerializer(Common::Serializer &ser); }; @@ -811,6 +629,7 @@ public: byte getType() const { return _type; } uint32 getSize() const { return _size; } T *getRawData() { return _data; } + const T *getRawData() const { return _data; } protected: int8 _type; @@ -834,7 +653,7 @@ struct ArrayTable : public Table<SciArray<reg_t> > { ArrayTable() : Table<SciArray<reg_t> >(SEG_TYPE_ARRAY) {} virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr); - virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const; + virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const; void saveLoadWithSerializer(Common::Serializer &ser); SegmentRef dereference(reg_t pointer); diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp index 04a1b8fbba..00480743cc 100644 --- a/engines/sci/engine/selector.cpp +++ b/engines/sci/engine/selector.cpp @@ -24,6 +24,7 @@ */ #include "sci/sci.h" +#include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" @@ -157,6 +158,9 @@ void Kernel::mapSelectors() { FIND_SELECTOR(scaleSignal); FIND_SELECTOR(scaleX); FIND_SELECTOR(scaleY); + FIND_SELECTOR(maxScale); + FIND_SELECTOR(vanishingX); + FIND_SELECTOR(vanishingY); FIND_SELECTOR(iconIndex); #ifdef ENABLE_SCI32 @@ -188,42 +192,37 @@ void writeSelector(SegManager *segMan, reg_t object, Selector selectorId, reg_t ObjVarRef address; if ((selectorId < 0) || (selectorId > (int)g_sci->getKernel()->getSelectorNamesSize())) { - warning("Attempt to write to invalid selector %d of" + error("Attempt to write to invalid selector %d of" " object at %04x:%04x.", selectorId, PRINT_REG(object)); return; } if (lookupSelector(segMan, object, selectorId, &address, NULL) != kSelectorVariable) - warning("Selector '%s' of object at %04x:%04x could not be" + error("Selector '%s' of object at %04x:%04x could not be" " written to", g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object)); else *address.getPointer(segMan) = value; } -int invokeSelectorArgv(EngineState *s, reg_t object, int selectorId, SelectorInvocation noinvalid, +void invokeSelector(EngineState *s, reg_t object, int selectorId, int k_argc, StackPtr k_argp, int argc, const reg_t *argv) { int i; int framesize = 2 + 1 * argc; - reg_t address; int slc_type; StackPtr stackframe = k_argp + k_argc; stackframe[0] = make_reg(0, selectorId); // The selector we want to call stackframe[1] = make_reg(0, argc); // Argument count - slc_type = lookupSelector(s->_segMan, object, selectorId, NULL, &address); + slc_type = lookupSelector(s->_segMan, object, selectorId, NULL, NULL); if (slc_type == kSelectorNone) { - warning("Selector '%s' of object at %04x:%04x could not be invoked", + error("Selector '%s' of object at %04x:%04x could not be invoked", g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object)); - if (noinvalid == kStopOnInvalidSelector) - error("[Kernel] Not recoverable: VM was halted"); - return 1; } if (slc_type == kSelectorVariable) { - warning("Attempting to invoke variable selector %s of object %04x:%04x", + error("Attempting to invoke variable selector %s of object %04x:%04x", g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object)); - return 0; } for (i = 0; i < argc; i++) @@ -238,24 +237,6 @@ int invokeSelectorArgv(EngineState *s, reg_t object, int selectorId, SelectorInv xstack->fp += argc + 2; run_vm(s, false); // Start a new vm - - return 0; -} - -int invokeSelector(EngineState *s, reg_t object, int selectorId, SelectorInvocation noinvalid, - int k_argc, StackPtr k_argp, int argc, ...) { - va_list argp; - reg_t *args = new reg_t[argc]; - - va_start(argp, argc); - for (int i = 0; i < argc; i++) - args[i] = va_arg(argp, reg_t); - va_end(argp); - - int retval = invokeSelectorArgv(s, object, selectorId, noinvalid, k_argc, k_argp, argc, args); - - delete[] args; - return retval; } SelectorType lookupSelector(SegManager *segMan, reg_t obj_location, Selector selectorId, ObjVarRef *varp, reg_t *fptr) { diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h index f50b9ab1b3..acb7912d8d 100644 --- a/engines/sci/engine/selector.h +++ b/engines/sci/engine/selector.h @@ -30,13 +30,118 @@ #include "sci/engine/vm_types.h" // for reg_t #include "sci/engine/vm.h" -#include "sci/engine/kernel.h" // for Kernel::_selectorCache namespace Sci { -enum SelectorInvocation { - kStopOnInvalidSelector = 0, - kContinueOnInvalidSelector = 1 +/** Contains selector IDs for a few selected selectors */ +struct SelectorCache { + SelectorCache() { + memset(this, 0, sizeof(*this)); + } + + // Statically defined selectors, (almost the) same in all SCI versions + Selector y; + Selector x; + Selector view, loop, cel; ///< Description of a specific image + Selector underBits; ///< Used by the graphics subroutines to store backupped BG pic data + Selector nsTop, nsLeft, nsBottom, nsRight; ///< View boundaries ('now seen') + Selector lsTop, lsLeft, lsBottom, lsRight; ///< Used by Animate() subfunctions and scroll list controls + Selector signal; ///< Used by Animate() to control a view's behaviour + Selector illegalBits; ///< Used by CanBeHere + Selector brTop, brLeft, brBottom, brRight; ///< Bounding Rectangle + // name, key, time + Selector text; ///< Used by controls + Selector elements; ///< Used by SetSynonyms() + // color, back + Selector mode; ///< Used by text controls (-> DrawControl()) + // style + Selector state, font, type;///< Used by controls + // window + Selector cursor, max; ///< Used by EditControl + // mark, who + Selector message; ///< Used by GetEvent + // edit + Selector play; ///< Play function (first function to be called) + Selector number; + Selector handle; ///< Replaced by nodePtr in SCI1+ + Selector nodePtr; ///< Replaces handle in SCI1+ + Selector client; ///< The object that wants to be moved + Selector dx, dy; ///< Deltas + Selector b_movCnt, b_i1, b_i2, b_di, b_xAxis, b_incr; ///< Various Bresenham vars + Selector xStep, yStep; ///< BR adjustments + Selector moveSpeed; ///< Used for DoBresen + Selector canBeHere; ///< Funcselector: Checks for movement validity in SCI0 + Selector heading, mover; ///< Used in DoAvoider + Selector doit; ///< Called (!) by the Animate() system call + Selector isBlocked, looper; ///< Used in DoAvoider + Selector priority; + Selector modifiers; ///< Used by GetEvent + Selector replay; ///< Replay function + // setPri, at, next, done, width + Selector wordFail, syntaxFail; ///< Used by Parse() + // semanticFail, pragmaFail + // said + Selector claimed; ///< Used generally by the event mechanism + // value, save, restore, title, button, icon, draw + Selector delete_; ///< Called by Animate() to dispose a view object + Selector z; + + // SCI1+ static selectors + Selector parseLang; + Selector printLang; ///< Used for i18n + Selector subtitleLang; + Selector size; + Selector points; ///< Used by AvoidPath() + Selector palette; + Selector dataInc; + // handle (in SCI1) + Selector min; ///< SMPTE time format + Selector sec; + Selector frame; + Selector vol; + Selector pri; + // perform + Selector moveDone; ///< used for DoBresen + + // SCI1 selectors which have been moved a bit in SCI1.1, but otherwise static + Selector cantBeHere; ///< Checks for movement avoidance in SCI1+. Replaces canBeHere + Selector topString; ///< SCI1 scroll lists use this instead of lsTop + Selector flags; + + // SCI1+ audio sync related selectors, not static. They're used for lip syncing in + // CD talkie games + Selector syncCue; ///< Used by DoSync() + Selector syncTime; + + // SCI1.1 specific selectors + Selector scaleSignal; //< Used by kAnimate() for cel scaling (SCI1.1+) + Selector scaleX, scaleY; ///< SCI1.1 view scaling + Selector maxScale; ///< SCI1.1 view scaling, limit for cel, when using global scaling + Selector vanishingX; ///< SCI1.1 view scaling, used by global scaling + Selector vanishingY; ///< SCI1.1 view scaling, used by global scaling + + // Used for auto detection purposes + Selector overlay; ///< Used to determine if a game is using old gfx functions or not + + // SCI1.1 Mac icon bar selectors + Selector iconIndex; ///< Used to index icon bar objects + +#ifdef ENABLE_SCI32 + Selector data; // Used by Array()/String() + Selector picture; // Used to hold the picture ID for SCI32 pictures + + Selector plane; + Selector top; + Selector left; + Selector bottom; + Selector right; + Selector resX; + Selector resY; + + Selector fore; + Selector back; + Selector dimmed; +#endif }; /** @@ -71,18 +176,8 @@ void writeSelector(SegManager *segMan, reg_t object, Selector selectorId, reg_t /** * Invokes a selector from an object. */ -int invokeSelector(EngineState *s, reg_t object, int selectorId, SelectorInvocation noinvalid, - int k_argc, StackPtr k_argp, int argc, ...); -int invokeSelectorArgv(EngineState *s, reg_t object, int selectorId, SelectorInvocation noinvalid, - int k_argc, StackPtr k_argp, int argc, const reg_t *argv); - -/** - * Kludge for use with invokeSelector(). Used for compatibility with compilers - * that cannot handle vararg macros. - */ -#define INV_SEL(s, _object_, _selector_, _noinvalid_) \ - s, _object_, g_sci->getKernel()->_selectorCache._selector_, _noinvalid_, argc, argv - +void invokeSelector(EngineState *s, reg_t object, int selectorId, + int k_argc, StackPtr k_argp, int argc = 0, const reg_t *argv = 0); } // End of namespace Sci diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index b4a04f8826..36b03c0ad9 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -29,6 +29,7 @@ #include "sci/debug.h" // for g_debug_sleeptime_factor #include "sci/event.h" +#include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/engine/vm.h" @@ -80,73 +81,91 @@ EngineState::~EngineState() { } void EngineState::reset(bool isRestoring) { -#ifdef USE_OLD_MUSIC_FUNCTIONS - sfx_init_flags = 0; -#endif - if (!isRestoring) { - script_000 = 0; - _gameObj = NULL_REG; - _memorySegmentSize = 0; - _soundCmd = 0; - restarting_flags = 0; + _fileHandles.resize(5); - execution_stack_base = 0; - _executionStackPosChanged = false; + abortScriptProcessing = kAbortNone; + } - _fileHandles.resize(5); + executionStackBase = 0; + _executionStackPosChanged = false; + stack_base = 0; + stack_top = 0; - r_acc = NULL_REG; - restAdjust = 0; - r_prev = NULL_REG; + restAdjust = 0; - stack_base = 0; - stack_top = 0; - } + r_acc = NULL_REG; + r_prev = NULL_REG; - last_wait_time = 0; + lastWaitTime = 0; - gc_countdown = 0; + gcCountDown = 0; _throttleCounter = 0; _throttleLastTime = 0; _throttleTrigger = false; - script_abort_flag = 0; - script_step_counter = 0; - script_gc_interval = GC_INTERVAL; + _lastSaveVirtualId = SAVEGAMEID_OFFICIALRANGE_START; + _lastSaveNewId = 0; - restoring = false; + scriptStepCounter = 0; + scriptGCInterval = GC_INTERVAL; } -void EngineState::wait(int16 ticks) { - uint32 time; +void EngineState::speedThrottler(uint32 neededSleep) { + if (_throttleTrigger) { + uint32 curTime = g_system->getMillis(); + uint32 duration = curTime - _throttleLastTime; + + if (duration < neededSleep) { + g_sci->sleep(neededSleep - duration); + _throttleLastTime = g_system->getMillis(); + } else { + _throttleLastTime = curTime; + } + _throttleTrigger = false; + } +} - time = g_system->getMillis(); - r_acc = make_reg(0, ((long)time - (long)last_wait_time) * 60 / 1000); - last_wait_time = time; +void EngineState::wait(int16 ticks) { + uint32 time = g_system->getMillis(); + r_acc = make_reg(0, ((long)time - (long)lastWaitTime) * 60 / 1000); + lastWaitTime = time; ticks *= g_debug_sleeptime_factor; - _event->sleep(ticks * 1000 / 60); + g_sci->sleep(ticks * 1000 / 60); +} + +void EngineState::initGlobals() { + Script *script_000 = _segMan->getScript(1); + + if (!script_000->_localsBlock) + error("Script 0 has no locals block"); + + variablesSegment[VAR_GLOBAL] = script_000->_localsSegment; + variablesBase[VAR_GLOBAL] = variables[VAR_GLOBAL] = script_000->_localsBlock->_locals.begin(); + variablesMax[VAR_GLOBAL] = script_000->_localsBlock->_locals.size(); } uint16 EngineState::currentRoomNumber() const { - return script_000->_localsBlock->_locals[13].toUint16(); + return variables[VAR_GLOBAL][13].toUint16(); } void EngineState::setRoomNumber(uint16 roomNumber) { - script_000->_localsBlock->_locals[13] = make_reg(0, roomNumber); + variables[VAR_GLOBAL][13] = make_reg(0, roomNumber); } void EngineState::shrinkStackToBase() { - uint size = execution_stack_base + 1; - assert(_executionStack.size() >= size); - Common::List<ExecStack>::iterator iter = _executionStack.begin(); - for (uint i = 0; i < size; ++i) - ++iter; - _executionStack.erase(iter, _executionStack.end()); + if (_executionStack.size() > 0) { + uint size = executionStackBase + 1; + assert(_executionStack.size() >= size); + Common::List<ExecStack>::iterator iter = _executionStack.begin(); + for (uint i = 0; i < size; ++i) + ++iter; + _executionStack.erase(iter, _executionStack.end()); + } } static kLanguage charToLanguage(const char c) { @@ -204,7 +223,7 @@ Common::String SciEngine::getSciLanguageString(const char *str, kLanguage lang, // Copy double-byte character char c2 = *(++seeker); if (!c2) { - warning("SJIS character %02X is missing second byte", c); + error("SJIS character %02X is missing second byte", c); break; } fullWidth += c; @@ -231,8 +250,8 @@ kLanguage SciEngine::getSciLanguage() { lang = K_LANG_ENGLISH; - if (_kernel->_selectorCache.printLang != -1) { - lang = (kLanguage)readSelectorValue(_gamestate->_segMan, _gamestate->_gameObj, SELECTOR(printLang)); + if (SELECTOR(printLang) != -1) { + lang = (kLanguage)readSelectorValue(_gamestate->_segMan, _gameObj, SELECTOR(printLang)); if ((getSciVersion() >= SCI_VERSION_1_1) || (lang == K_LANG_NONE)) { // If language is set to none, we use the language from the game detector. @@ -265,21 +284,27 @@ kLanguage SciEngine::getSciLanguage() { default: lang = K_LANG_ENGLISH; } - - // Store language in printLang selector - writeSelectorValue(_gamestate->_segMan, _gamestate->_gameObj, SELECTOR(printLang), lang); } } return lang; } +void SciEngine::setSciLanguage(kLanguage lang) { + if (SELECTOR(printLang) != -1) + writeSelectorValue(_gamestate->_segMan, _gameObj, SELECTOR(printLang), lang); +} + +void SciEngine::setSciLanguage() { + setSciLanguage(getSciLanguage()); +} + Common::String SciEngine::strSplit(const char *str, const char *sep) { kLanguage lang = getSciLanguage(); kLanguage subLang = K_LANG_NONE; - if (_kernel->_selectorCache.subtitleLang != -1) { - subLang = (kLanguage)readSelectorValue(_gamestate->_segMan, _gamestate->_gameObj, SELECTOR(subtitleLang)); + if (SELECTOR(subtitleLang) != -1) { + subLang = (kLanguage)readSelectorValue(_gamestate->_segMan, _gameObj, SELECTOR(subtitleLang)); } kLanguage secondLang; diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index bcdf66d6ef..243a460645 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -41,17 +41,21 @@ namespace Common { #include "sci/parser/vocabulary.h" -#ifdef USE_OLD_MUSIC_FUNCTIONS -#include "sci/sound/iterator/core.h" -#endif #include "sci/sound/soundcmd.h" namespace Sci { -class SciEvent; +class EventManager; class MessageState; class SoundCommandParser; +enum AbortGameState { + kAbortNone = 0, + kAbortLoadGame = 1, + kAbortRestartGame = 2, + kAbortQuitGame = 3 +}; + class DirSeeker { protected: reg_t _outbuffer; @@ -72,11 +76,15 @@ enum { MAX_SAVE_DIR_SIZE = MAXPATHLEN }; -/** values for EngineState.restarting_flag */ enum { - SCI_GAME_IS_NOT_RESTARTING = 0, - SCI_GAME_WAS_RESTARTED = 1, - SCI_GAME_IS_RESTARTING_NOW = 2 + MAX_SAVEGAME_NR = 20 /**< Maximum number of savegames */ +}; + +// We assume that scripts give us savegameId 0->999 for creating a new save slot +// and savegameId 1000->1999 for existing save slots ffs. kfile.cpp +enum { + SAVEGAMEID_OFFICIALRANGE_START = 1000, + SAVEGAMEID_OFFICIALRANGE_END = 1999 }; class FileHandle { @@ -105,19 +113,11 @@ public: /* Non-VM information */ - SciEvent *_event; // Event handling - -#ifdef USE_OLD_MUSIC_FUNCTIONS - SfxState _sound; /**< sound subsystem */ - int sfx_init_flags; /**< flags the sfx subsystem was initialised with */ -#endif - SoundCommandParser *_soundCmd; - - byte restarting_flags; /**< Flags used for restarting */ - - uint32 game_start_time; /**< The time at which the interpreter was started */ - uint32 last_wait_time; /**< The last time the game invoked Wait() */ + uint32 gameStartTime; /**< The time at which the interpreter was started */ + uint32 lastWaitTime; /**< The last time the game invoked Wait() */ + uint32 _screenUpdateTime; /**< The last time the game updated the screen */ + void speedThrottler(uint32 neededSleep); void wait(int16 ticks); uint32 _throttleCounter; /**< total times kAnimate was invoked */ @@ -130,6 +130,9 @@ public: DirSeeker _dirseeker; + uint _lastSaveVirtualId; // last virtual id fed to kSaveGame, if no kGetSaveFiles was called inbetween + uint _lastSaveNewId; // last newly created filename-id by kSaveGame + public: /* VM Information */ @@ -138,12 +141,11 @@ public: * When called from kernel functions, the vm is re-started recursively on * the same stack. This variable contains the stack base for the current vm. */ - int execution_stack_base; + int executionStackBase; bool _executionStackPosChanged; /**< Set to true if the execution stack position should be re-evaluated by the vm */ reg_t r_acc; /**< Accumulator */ - int16 restAdjust; /**< &rest register (only used for save games) */ - int16 restAdjustCur; /**< current &rest register (only used for save games) */ + int16 restAdjust; /**< current &rest register */ reg_t r_prev; /**< previous comparison result */ StackPtr stack_base; /**< Pointer to the least stack element */ @@ -152,35 +154,31 @@ public: // Script state ExecStack *xs; reg_t *variables[4]; ///< global, local, temp, param, as immediate pointers - reg_t *variables_base[4]; ///< Used for referencing VM ops - SegmentId variables_seg[4]; ///< Same as above, contains segment IDs - int variables_max[4]; ///< Max. values for all variables + reg_t *variablesBase[4]; ///< Used for referencing VM ops + SegmentId variablesSegment[4]; ///< Same as above, contains segment IDs + int variablesMax[4]; ///< Max. values for all variables - Script *script_000; /**< script 000, e.g. for globals */ + AbortGameState abortScriptProcessing; + bool gameWasRestarted; - int loadFromLauncher; - - /** - * Set this to 1 to abort script execution immediately. Aborting will - * leave the debug exec stack intact. - * Set it to 2 to force a replay afterwards. - */ - int script_abort_flag; // Set to 1 to abort execution. Set to 2 to force a replay afterwards - int script_step_counter; // Counts the number of steps executed - int script_gc_interval; // Number of steps in between gcs + int scriptStepCounter; // Counts the number of steps executed + int scriptGCInterval; // Number of steps in between gcs uint16 currentRoomNumber() const; void setRoomNumber(uint16 roomNumber); /** + * Sets global variables from script 0 + */ + void initGlobals(); + + /** * Shrink execution stack to size. - * Contains an assert it is not already smaller. + * Contains an assert if it is not already smaller. */ void shrinkStackToBase(); - reg_t _gameObj; /**< Pointer to the game object */ - - int gc_countdown; /**< Number of kernel calls until next gc */ + int gcCountDown; /**< Number of kernel calls until next gc */ public: MessageState *_msgState; @@ -197,8 +195,6 @@ public: * Resets the engine state. */ void reset(bool isRestoring); - - bool restoring; /**< A flag to indicate if a game is being restored */ }; } // End of namespace Sci diff --git a/engines/sci/engine/static_selectors.cpp b/engines/sci/engine/static_selectors.cpp index 0f558f2dc8..85089e74c8 100644 --- a/engines/sci/engine/static_selectors.cpp +++ b/engines/sci/engine/static_selectors.cpp @@ -100,13 +100,24 @@ static const SelectorRemap sciSelectorRemap[] = { { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "moveDone", 170 }, { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "points", 316 }, { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "flags", 368 }, - { SCI_VERSION_1_EARLY, SCI_VERSION_1_1, "nodePtr", 44 }, - { SCI_VERSION_1_LATE, SCI_VERSION_1_1, "cantBeHere", 57 }, - { SCI_VERSION_1_EARLY, SCI_VERSION_1_1, "topString", 101 }, - { SCI_VERSION_1_EARLY, SCI_VERSION_1_1, "flags", 102 }, + { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "nodePtr", 44 }, + { SCI_VERSION_1_LATE, SCI_VERSION_1_LATE, "cantBeHere", 57 }, + { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "topString", 101 }, + { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "flags", 102 }, + // SCI1.1 + { SCI_VERSION_1_1, SCI_VERSION_1_1, "nodePtr", 41 }, + { SCI_VERSION_1_1, SCI_VERSION_1_1, "cantBeHere", 54 }, + { SCI_VERSION_1_1, SCI_VERSION_1_1, "topString", 98 }, + { SCI_VERSION_1_1, SCI_VERSION_1_1, "flags", 99 }, + // quitGame + // restart + // hide { SCI_VERSION_1_1, SCI_VERSION_1_1,"scaleSignal", 103 }, { SCI_VERSION_1_1, SCI_VERSION_1_1, "scaleX", 104 }, { SCI_VERSION_1_1, SCI_VERSION_1_1, "scaleY", 105 }, + { SCI_VERSION_1_1, SCI_VERSION_1_1, "maxScale", 106 }, + { SCI_VERSION_1_1, SCI_VERSION_1_1, "vanishingX", 107 }, + { SCI_VERSION_1_1, SCI_VERSION_1_1, "vanishingY", 108 }, { SCI_VERSION_NONE, SCI_VERSION_NONE, 0, 0 } }; @@ -139,16 +150,26 @@ Common::StringArray Kernel::checkStaticSelectorNames() { } for (const SelectorRemap *selectorRemap = sciSelectorRemap; selectorRemap->slot; ++selectorRemap) { - uint32 slot = selectorRemap->slot; - if (selectorRemap->slot >= names.size()) - names.resize(selectorRemap->slot + 1); if (getSciVersion() >= selectorRemap->minVersion && getSciVersion() <= selectorRemap->maxVersion) { - // The SCI1 selectors we use exist in SCI1.1 too, offset by 3 - if (selectorRemap->minVersion >= SCI_VERSION_1_EARLY && getSciVersion() == SCI_VERSION_1_1) - slot -= 3; + const uint32 slot = selectorRemap->slot; + if (slot >= names.size()) + names.resize(slot + 1); names[slot] = selectorRemap->name; } } + + if (g_sci->getGameId() == GID_HOYLE4) { + // The demo of Hoyle 4 is one of the few demos with lip syncing and no selector vocabulary. + // This needs two selectors, "syncTime" and "syncCue", which keep changing positions in each + // game. Usually, games with speech and lip sync have a selector vocabulary, so we don't need + // to set these two selectors, but we need for Hoyle... + if (names.size() < 276) + names.resize(276); + + names[274] = "syncTime"; + names[275] = "syncCue"; + } + #ifdef ENABLE_SCI32 } else { // SCI2+ diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 1dcdf450ba..8108440102 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -30,24 +30,104 @@ #include "sci/sci.h" #include "sci/console.h" -#include "sci/debug.h" // for g_debugState #include "sci/resource.h" #include "sci/engine/features.h" #include "sci/engine/state.h" #include "sci/engine/kernel.h" -#include "sci/engine/seg_manager.h" #include "sci/engine/script.h" +#include "sci/engine/seg_manager.h" +#include "sci/engine/selector.h" // for SELECTOR #include "sci/engine/gc.h" namespace Sci { const reg_t NULL_REG = {0, 0}; const reg_t SIGNAL_REG = {0, SIGNAL_OFFSET}; - +const reg_t TRUE_REG = {0, 1}; //#define VM_DEBUG_SEND #define SCI_XS_CALLEE_LOCALS ((SegmentId)-1) +#define END Script_None + +opcode_format g_opcode_formats[128][4] = { + /*00*/ + {Script_None}, {Script_None}, {Script_None}, {Script_None}, + /*04*/ + {Script_None}, {Script_None}, {Script_None}, {Script_None}, + /*08*/ + {Script_None}, {Script_None}, {Script_None}, {Script_None}, + /*0C*/ + {Script_None}, {Script_None}, {Script_None}, {Script_None}, + /*10*/ + {Script_None}, {Script_None}, {Script_None}, {Script_None}, + /*14*/ + {Script_None}, {Script_None}, {Script_None}, {Script_SRelative, END}, + /*18*/ + {Script_SRelative, END}, {Script_SRelative, END}, {Script_SVariable, END}, {Script_None}, + /*1C*/ + {Script_SVariable, END}, {Script_None}, {Script_None}, {Script_Variable, END}, + /*20*/ + {Script_SRelative, Script_Byte, END}, {Script_Variable, Script_Byte, END}, {Script_Variable, Script_Byte, END}, {Script_Variable, Script_SVariable, Script_Byte, END}, + /*24 (24=ret)*/ + {Script_End}, {Script_Byte, END}, {Script_Invalid}, {Script_Invalid}, + /*28*/ + {Script_Variable, END}, {Script_Invalid}, {Script_Byte, END}, {Script_Variable, Script_Byte, END}, + /*2C*/ + {Script_SVariable, END}, {Script_SVariable, Script_Variable, END}, {Script_None}, {Script_Invalid}, + /*30*/ + {Script_None}, {Script_Property, END}, {Script_Property, END}, {Script_Property, END}, + /*34*/ + {Script_Property, END}, {Script_Property, END}, {Script_Property, END}, {Script_Property, END}, + /*38*/ + {Script_Property, END}, {Script_SRelative, END}, {Script_SRelative, END}, {Script_None}, + /*3C*/ + {Script_None}, {Script_None}, {Script_None}, {Script_Word}, + /*40-4F*/ + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + /*50-5F*/ + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + /*60-6F*/ + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + /*70-7F*/ + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END} +}; +#undef END + +// TODO: script_adjust_opcode_formats should probably be part of the +// constructor (?) of a VirtualMachine or a ScriptManager class. +void script_adjust_opcode_formats() { + if (g_sci->_features->detectLofsType() != SCI_VERSION_0_EARLY) { + g_opcode_formats[op_lofsa][0] = Script_Offset; + g_opcode_formats[op_lofss][0] = Script_Offset; + } + +#ifdef ENABLE_SCI32 + // In SCI32, some arguments are now words instead of bytes + if (getSciVersion() >= SCI_VERSION_2) { + g_opcode_formats[op_calle][2] = Script_Word; + g_opcode_formats[op_callk][1] = Script_Word; + g_opcode_formats[op_super][1] = Script_Word; + g_opcode_formats[op_send][0] = Script_Word; + g_opcode_formats[op_self][0] = Script_Word; + g_opcode_formats[op_call][1] = Script_Word; + g_opcode_formats[op_callb][1] = Script_Word; + } +#endif +} + /** * Adds an entry to the top of the execution stack. * @@ -59,6 +139,8 @@ const reg_t SIGNAL_REG = {0, SIGNAL_OFFSET}; * @param[in] argp Heap pointer to the first parameter * @param[in] selector The selector by which it was called or * NULL_SELECTOR if n.a. For debugging. + * @param[in] exportId The exportId by which it was called or + * -1 if n.a. For debugging. * @param[in] sendp Pointer to the object which the message was * sent to. Equal to objp for anything but super. * @param[in] origin Number of the execution stack element this @@ -69,7 +151,7 @@ const reg_t SIGNAL_REG = {0, SIGNAL_OFFSET}; * @return A pointer to the new exec stack TOS entry */ static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t pc, StackPtr sp, - reg_t objp, int argc, StackPtr argp, Selector selector, + reg_t objp, int argc, StackPtr argp, Selector selector, int exportId, int localCallOffset, reg_t sendp, int origin, SegmentId local_segment); @@ -94,20 +176,24 @@ static ExecStack *add_exec_stack_varselector(Common::List<ExecStack> &execStack, // validation functionality -#ifndef DISABLE_VALIDATIONS - static reg_t &validate_property(Object *obj, int index) { // A static dummy reg_t, which we return if obj or index turn out to be // invalid. Note that we cannot just return NULL_REG, because client code // may modify the value of the returned reg_t. static reg_t dummyReg = NULL_REG; + // FIXME/TODO: Where does this occur? Returning a dummy reg here could lead + // to all sorts of issues! Turned it into an error for now... + // If this occurs, it means there's probably something wrong with the garbage + // collector, so don't hide it with fake return values if (!obj) { - debugC(2, kDebugLevelVM, "[VM] Sending to disposed object!"); - return dummyReg; + error("validate_property: Sending to disposed object"); + //return dummyReg; } if (index < 0 || (uint)index >= obj->getVarCount()) { + // This is same way sierra does it and there are some games, that contain such scripts like + // iceman script 998 (fred::canBeHere, executed right at the start) debugC(2, kDebugLevelVM, "[VM] Invalid property #%d (out of [0..%d]) requested!", index, obj->getVarCount()); return dummyReg; @@ -127,7 +213,10 @@ static StackPtr validate_stack_addr(EngineState *s, StackPtr sp) { static int validate_arithmetic(reg_t reg) { if (reg.segment) { - warning("[VM] Attempt to read arithmetic value from non-zero segment [%04x]", reg.segment); + // The results of this are likely unpredictable... It most likely means that a kernel function is returning something wrong. + // If such an error occurs, we usually need to find the last kernel function called and check its return value. Check + // callKernelFunc() below + error("[VM] Attempt to read arithmetic value from non-zero segment [%04x]. Address: %04x:%04x", reg.segment, PRINT_REG(reg)); return 0; } @@ -135,15 +224,10 @@ static int validate_arithmetic(reg_t reg) { } static int signed_validate_arithmetic(reg_t reg) { - if (reg.segment) { - warning("[VM] Attempt to read arithmetic value from non-zero segment [%04x]", reg.segment); - return 0; - } - - return (int16)reg.offset; + return (int16)validate_arithmetic(reg); } -static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, int index, int line) { +static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, int index) { const char *names[4] = {"global", "local", "temp", "param"}; if (index < 0 || index >= max) { @@ -158,10 +242,15 @@ static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, in if (type == VAR_PARAM || type == VAR_TEMP) { int total_offset = r - stack_base; if (total_offset < 0 || total_offset >= VM_STACK_SIZE) { - warning("%s", txt.c_str()); - warning("[VM] Access would be outside even of the stack (%d); access denied", total_offset); + // Fatal, as the game is trying to do an OOB access + error("%s. [VM] Access would be outside even of the stack (%d); access denied", txt.c_str(), total_offset); return false; } else { + // WORKAROUND: Mixed-Up Mother Goose tries to use an invalid parameter in Event::new(). + // Just skip around it here so we don't error out in validate_arithmetic. + if (g_sci->getGameId() == GID_MOTHERGOOSE && getSciVersion() <= SCI_VERSION_1_1 && type == VAR_PARAM && index == 1) + return false; + debugC(2, kDebugLevelVM, "%s", txt.c_str()); debugC(2, kDebugLevelVM, "[VM] Access within stack boundaries; access granted."); return true; @@ -173,15 +262,139 @@ static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, in return true; } -static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) { - if (validate_variable(r, stack_base, type, max, index, line)) +struct SciTrackOriginReply { + int scriptNr; + Common::String objectName; + Common::String methodName; + int localCallOffset; +}; + +static reg_t trackOriginAndFindWorkaround(int index, const SciWorkaroundEntry *workaroundList, SciTrackOriginReply *trackOrigin) { + EngineState *state = g_sci->getEngineState(); + ExecStack *lastCall = state->xs; + Script *local_script = state->_segMan->getScriptIfLoaded(lastCall->local_segment); + int curScriptNr = local_script->getScriptNumber(); + + if (lastCall->debugLocalCallOffset != -1) { + // if lastcall was actually a local call search back for a real call + Common::List<ExecStack>::iterator callIterator = state->_executionStack.end(); + while (callIterator != state->_executionStack.begin()) { + callIterator--; + ExecStack loopCall = *callIterator; + if ((loopCall.debugSelector != -1) || (loopCall.debugExportId != -1)) { + lastCall->debugSelector = loopCall.debugSelector; + lastCall->debugExportId = loopCall.debugExportId; + break; + } + } + } + + Common::String curObjectName = state->_segMan->getObjectName(lastCall->sendp); + Common::String curMethodName; + const SciGameId gameId = g_sci->getGameId(); + + if (lastCall->type == EXEC_STACK_TYPE_CALL) { + if (lastCall->debugSelector != -1) { + curMethodName = g_sci->getKernel()->getSelectorName(lastCall->debugSelector); + } else if (lastCall->debugExportId != -1) { + curObjectName = ""; + curMethodName = curMethodName.printf("export %d", lastCall->debugExportId); + } + } + + if (workaroundList) { + // Search if there is a workaround for this one + const SciWorkaroundEntry *workaround; + int16 inheritanceLevel = 0; + Common::String searchObjectName = curObjectName; + reg_t searchObject = lastCall->sendp; + do { + workaround = workaroundList; + while (workaround->objectName) { + if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr + && ((workaround->inheritanceLevel == -1) || (workaround->inheritanceLevel == inheritanceLevel)) + && (workaround->objectName == searchObjectName) + && workaround->methodName == curMethodName && workaround->localCallOffset == lastCall->debugLocalCallOffset && workaround->index == index) { + // Workaround found + return workaround->newValue; + } + workaround++; + } + + // Go back to the parent + inheritanceLevel++; + searchObject = state->_segMan->getObject(searchObject)->getSuperClassSelector(); + if (!searchObject.isNull()) + searchObjectName = state->_segMan->getObjectName(searchObject); + } while (!searchObject.isNull()); // no parent left? + } + + // give caller origin data + trackOrigin->objectName = curObjectName; + trackOrigin->methodName = curMethodName; + trackOrigin->scriptNr = curScriptNr; + trackOrigin->localCallOffset = lastCall->debugLocalCallOffset; + return make_reg(0xFFFF, 0xFFFF); +} + +// gameID, scriptNr,lvl, object-name, method-name, call, index, replace +static const SciWorkaroundEntry uninitializedReadWorkarounds[] = { + { GID_LAURABOW2, 24, 0, "gcWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu + { GID_FREDDYPHARKAS, 24, 0, "gcWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu + { GID_FREDDYPHARKAS, 31, 0, "quitWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu + { GID_GK2, 11, 0, "", "export 10", -1, 3, { 0, 0 } }, // called when the game starts + { GID_JONES, 232, 0, "weekendText", "draw", 0x3d3, 0, { 0, 0 } }, // jones/cd only - gets called during the game + { GID_JONES, 255, 0, "", "export 0", -1, 13, { 0, 0 } }, // jones/ega&vga only - called when the game starts + { GID_JONES, 255, 0, "", "export 0", -1, 14, { 0, 0 } }, // jones/ega&vga only - called when the game starts + { GID_LSL1, 720, 0, "rm720", "init", -1, 0, { 0, 0 } }, // age check room + { GID_LSL3, 997, 0, "TheMenuBar", "handleEvent", -1, 1, { 0, 0xf } }, // when setting volume the first time, this temp is used to set volume on entry (normally it would have been initialized to 's') + { GID_LSL6, 928, -1, "Narrator", "startText", -1, 0, { 0, 0 } }, // used by various objects that are even translated in foreign versions, that's why we use the base-class + { GID_ISLANDBRAIN, 140, 0, "piece", "init", -1, 3, { 0, 1 } }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 + { GID_ISLANDBRAIN, 268, 0, "anElement", "select", -1, 0, { 0, 0 } }, // elements puzzle, gets used before super TextIcon + { GID_KQ5, 0, 0, "", "export 29", -1, 3, { 0, 0 } }, // called when playing harp for the harpies, is used for kDoAudio + { GID_KQ5, 25, 0, "rm025", "doit", -1, 0, { 0, 0 } }, // inside witch forest, where the walking rock is + { GID_KQ6, 903, 0, "controlWin", "open", -1, 4, { 0, 0 } }, // when opening the controls window (save, load etc) + { GID_KQ6, 500, 0, "rm500", "init", -1, 0, { 0, 0 } }, // going to island of the beast + { GID_KQ6, 520, 0, "rm520", "init", -1, 0, { 0, 0 } }, // going to boiling water trap on beast isle + { GID_KQ6, 30, 0, "rats", "changeState", -1, 0, { 0, 0 } }, // rats in the catacombs + { GID_LSL6, 85, 0, "washcloth", "doVerb", -1, 0, { 0, 0 } }, // washcloth in inventory + { GID_SQ1, 703, 0, "", "export 1", -1, 0, { 0, 0 } }, // sub that's called from several objects while on sarien battle cruiser + { GID_SQ1, 703, 0, "firePulsar", "changeState", 0x18a, 0, { 0, 0 } }, // export 1, but called locally (when shooting at aliens) + { GID_SQ4, 928, 0, "Narrator", "startText", -1, 1000, { 0, 1 } }, // sq4cd: method returns this to the caller + { GID_SQ6, 0, 0, "SQ6", "init", -1, 2, { 0, 0 } }, // called when the game starts + { GID_SQ6, 64950, 0, "View", "handleEvent", -1, 0, { 0, 0 } }, // called when pressing "Start game" in the main menu + SCI_WORKAROUNDENTRY_TERMINATOR +}; + +static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, reg_t default_value) { + if (validate_variable(r, stack_base, type, max, index)) { + if (r[index].segment == 0xffff) { + switch (type) { + case VAR_TEMP: { + // Uninitialized read on a temp + // We need to find correct replacements for each situation manually + SciTrackOriginReply originReply; + r[index] = trackOriginAndFindWorkaround(index, uninitializedReadWorkarounds, &originReply); + if ((r[index].segment == 0xFFFF) && (r[index].offset == 0xFFFF)) + error("Uninitialized read for temp %d from method %s::%s (script %d, localCall %x)", index, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); + break; + } + case VAR_PARAM: + // Out-of-bounds read for a parameter that goes onto stack and hits an uninitialized temp + // We return 0 currently in that case + warning("Read for a parameter goes out-of-bounds, onto the stack and gets uninitialized temp"); + return NULL_REG; + default: + break; + } + } return r[index]; - else + } else return default_value; } -static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t value, SegManager *segMan, Kernel *kernel) { - if (validate_variable(r, stack_base, type, max, index, line)) { +static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, int index, reg_t value, SegManager *segMan, Kernel *kernel) { + if (validate_variable(r, stack_base, type, max, index)) { // WORKAROUND: This code is needed to work around a probable script bug, or a // limitation of the original SCI engine, which can be observed in LSL5. @@ -200,44 +413,34 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i // stopGroop object, which points to ego, to the new ego object. If this is not // done, ego's movement will not be updated properly, so the result is // unpredictable (for example in LSL5, Patti spins around instead of walking). - if (index == 0 && type == VAR_GLOBAL) { // global 0 is ego + if (index == 0 && type == VAR_GLOBAL && getSciVersion() > SCI_VERSION_0_EARLY) { // global 0 is ego reg_t stopGroopPos = segMan->findObjectByName("stopGroop"); if (!stopGroopPos.isNull()) { // does the game have a stopGroop object? // Find the "client" member variable of the stopGroop object, and update it ObjVarRef varp; - if (lookupSelector(segMan, stopGroopPos, kernel->_selectorCache.client, &varp, NULL) == kSelectorVariable) { + if (lookupSelector(segMan, stopGroopPos, SELECTOR(client), &varp, NULL) == kSelectorVariable) { reg_t *clientVar = varp.getPointer(segMan); *clientVar = value; } } } + // If we are writing an uninitialized value into a temp, we remove the uninitialized segment + // this happens at least in sq1/room 44 (slot-machine), because a send is missing parameters, then + // those parameters are taken from uninitialized stack and afterwards they are copied back into temps + // if we don't remove the segment, we would get false-positive uninitialized reads later + if (type == VAR_TEMP && value.segment == 0xffff) + value.segment = 0; + r[index] = value; } } -#else -// Non-validating alternatives - -# define validate_stack_addr(s, sp) sp -# define validate_arithmetic(r) ((r).offset) -# define signed_validate_arithmetic(r) ((int16)(r).offset) -# define validate_variable(r, sb, t, m, i, l) -# define validate_read_var(r, sb, t, m, i, l, dv) ((r)[i]) -# define validate_write_var(r, sb, t, m, i, l, v, sm, k) ((r)[i] = (v)) -# define validate_property(o, p) ((o)->_variables[p]) - -#endif - -#define READ_VAR(type, index, def) validate_read_var(s->variables[type], s->stack_base, type, s->variables_max[type], index, __LINE__, def) -#define WRITE_VAR(type, index, value) validate_write_var(s->variables[type], s->stack_base, type, s->variables_max[type], index, __LINE__, value, s->_segMan, g_sci->getKernel()) +#define READ_VAR(type, index) validate_read_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, s->r_acc) +#define WRITE_VAR(type, index, value) validate_write_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, value, s->_segMan, g_sci->getKernel()) #define WRITE_VAR16(type, index, value) WRITE_VAR(type, index, make_reg(0, value)); #define ACC_ARITHMETIC_L(op) make_reg(0, (op validate_arithmetic(s->r_acc))) -#define ACC_AUX_LOAD() aux_acc = signed_validate_arithmetic(s->r_acc) -#define ACC_AUX_STORE() s->r_acc = make_reg(0, aux_acc) - -#define OBJ_PROPERTY(o, p) (validate_property(o, p)) // Operating on the stack // 16 bit: @@ -247,12 +450,32 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i #define PUSH32(a) (*(validate_stack_addr(s, (s->xs->sp)++)) = (a)) #define POP32() (*(validate_stack_addr(s, --(s->xs->sp)))) +bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) { + if (_debugState._activeBreakpointTypes & BREAK_EXPORT) { + uint32 bpaddress; + + bpaddress = (script << 16 | pubfunct); + + Common::List<Breakpoint>::const_iterator bp; + for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) { + if (bp->type == BREAK_EXPORT && bp->address == bpaddress) { + _console->DebugPrintf("Break on script %d, export %d\n", script, pubfunct); + _debugState.debugging = true; + _debugState.breakpointWasHit = true; + return true;; + } + } + } + + return false; +} + ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackPtr sp, reg_t calling_obj, uint16 argc, StackPtr argp) { int seg = s->_segMan->getScriptSegment(script); Script *scr = s->_segMan->getScriptIfLoaded(seg); if (!scr || scr->isMarkedAsDeleted()) { // Script not present yet? - seg = script_instantiate(g_sci->getResMan(), s->_segMan, script); + seg = s->_segMan->instantiateScript(script); scr = s->_segMan->getScript(seg); } @@ -270,24 +493,9 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP } // Check if a breakpoint is set on this method - if (g_debugState._activeBreakpointTypes & BREAK_EXPORT) { - uint32 bpaddress; - - bpaddress = (script << 16 | pubfunct); - - Common::List<Breakpoint>::const_iterator bp; - for (bp = g_debugState._breakpoints.begin(); bp != g_debugState._breakpoints.end(); ++bp) { - if (bp->type == BREAK_EXPORT && bp->address == bpaddress) { - Console *con = g_sci->getSciDebugger(); - con->DebugPrintf("Break on script %d, export %d\n", script, pubfunct); - g_debugState.debugging = true; - g_debugState.breakpointWasHit = true; - break; - } - } - } + g_sci->checkExportBreakpoint(script, pubfunct); - return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, calling_obj, s->_executionStack.size()-1, seg); + return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, pubfunct, -1, calling_obj, s->_executionStack.size()-1, seg); } @@ -297,7 +505,7 @@ static void _exec_varselectors(EngineState *s) { ExecStack &xs = s->_executionStack.back(); reg_t *var = xs.getVarPointer(s->_segMan); if (!var) { - warning("Invalid varselector exec stack entry"); + error("Invalid varselector exec stack entry"); } else { // varselector access? if (xs.argc) { // write? @@ -325,6 +533,30 @@ struct CallsStruct { int type; /**< Same as ExecStack.type */ }; +bool SciEngine::checkSelectorBreakpoint(reg_t send_obj, int selector) { + if (_debugState._activeBreakpointTypes & BREAK_SELECTOR) { + char method_name[256]; + + sprintf(method_name, "%s::%s", _gamestate->_segMan->getObjectName(send_obj), getKernel()->getSelectorName(selector).c_str()); + + Common::List<Breakpoint>::const_iterator bp; + for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) { + int cmplen = bp->name.size(); + if (bp->name.lastChar() != ':') + cmplen = 256; + + if (bp->type == BREAK_SELECTOR && !strncmp(bp->name.c_str(), method_name, cmplen)) { + _console->DebugPrintf("Break on %s (in [%04x:%04x])\n", method_name, PRINT_REG(send_obj)); + _debugState.debugging = true; + _debugState.breakpointWasHit = true; + return true; + } + } + } + + return false; +} + ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPtr sp, int framesize, StackPtr argp) { // send_obj and work_obj are equal for anything but 'super' // Returns a pointer to the TOS exec_stack element @@ -349,27 +581,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt } // Check if a breakpoint is set on this method - if (g_debugState._activeBreakpointTypes & BREAK_SELECTOR) { - char method_name[256]; - - sprintf(method_name, "%s::%s", s->_segMan->getObjectName(send_obj), g_sci->getKernel()->getSelectorName(selector).c_str()); - - Common::List<Breakpoint>::const_iterator bp; - for (bp = g_debugState._breakpoints.begin(); bp != g_debugState._breakpoints.end(); ++bp) { - int cmplen = bp->name.size(); - if (bp->name.lastChar() != ':') - cmplen = 256; - - if (bp->type == BREAK_SELECTOR && !strncmp(bp->name.c_str(), method_name, cmplen)) { - Console *con = g_sci->getSciDebugger(); - con->DebugPrintf("Break on %s (in [%04x:%04x])\n", method_name, PRINT_REG(send_obj)); - printSendActions = true; - g_debugState.debugging = true; - g_debugState.breakpointWasHit = true; - break; - } - } - } + printSendActions = g_sci->checkSelectorBreakpoint(send_obj, selector); #ifdef VM_DEBUG_SEND printf("Send to %04x:%04x, selector %04x (%s):", PRINT_REG(send_obj), selector, g_sci->getKernel()->getSelectorName(selector).c_str()); @@ -405,19 +617,30 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt } if (argc > 1) { - // argc can indeed be bigger than 1 in some cases, and it seems correct - // (i.e. we should skip that many bytes later on)... question is, why - // does this occur? Could such calls be used to point to data after X - // bytes in the heap? What are the skipped bytes in this case? - // In SQ4CD, this occurs with the returnVal selector of object - // Sq4GlobalNarrator when the game starts, and right after the narrator - // is heard (e.g. after he talks when examining something) - reg_t oldReg = *varp.getPointer(s->_segMan); - reg_t newReg = argp[1]; - warning("send_selector(): argc = %d while modifying variable selector " - "%x (%s) of object %04x:%04x (%s) from %04x:%04x to %04x:%04x", - argc, selector, g_sci->getKernel()->getSelectorName(selector).c_str(), PRINT_REG(send_obj), - s->_segMan->getObjectName(send_obj), PRINT_REG(oldReg), PRINT_REG(newReg)); + // argc can indeed be bigger than 1 in some cases, and it's usually the + // result of a script bug + + const char *objectName = s->_segMan->getObjectName(send_obj); + + if (!strcmp(objectName, "Sq4GlobalNarrator") && selector == 606) { + // SQ4 has a script bug in the Sq4GlobalNarrator object when invoking the + // returnVal selector, which doesn't affect gameplay, thus don't diplay it + } else if (!strcmp(objectName, "longSong") && selector == 3 && g_sci->getGameId() == GID_QFG1) { + // QFG1VGA has a script bug in the longSong object when invoking the + // loop selector, which doesn't affect gameplay, thus don't diplay it + } else if (!strcmp(objectName, "PuzPiece") && selector == 77 && g_sci->getGameId() == GID_CASTLEBRAIN) { + // Castle of Dr. Brain has a script bug in the PuzPiece object when invoking + // the value selector, which doesn't affect gameplay, thus don't display it + } else { + // Unknown script bug, show it. Usually these aren't fatal. + reg_t oldReg = *varp.getPointer(s->_segMan); + reg_t newReg = argp[1]; + const char *selectorName = g_sci->getKernel()->getSelectorName(selector).c_str(); + warning("send_selector(): argc = %d while modifying variable selector " + "%x (%s) of object %04x:%04x (%s) from %04x:%04x to %04x:%04x", + argc, selector, selectorName, PRINT_REG(send_obj), + objectName, PRINT_REG(oldReg), PRINT_REG(newReg)); + } } { @@ -444,7 +667,28 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt printf(") at %04x:%04x\n", PRINT_REG(funcp)); #endif // VM_DEBUG_SEND if (printSendActions) { - debug("[invoke selector]\n"); + printf("[invoke selector]"); +#ifndef VM_DEBUG_SEND + int displaySize = 0; + for (int argNr = 1; argNr <= argc; argNr++) { + if (argNr == 1) + printf(" - "); + reg_t curParam = argp[argNr]; + if (curParam.segment) { + printf("[%04x:%04x] ", PRINT_REG(curParam)); + displaySize += 12; + } else { + printf("[%04x] ", curParam.offset); + displaySize += 7; + } + if (displaySize > 50) { + if (argNr < argc) + printf("..."); + break; + } + } +#endif + printf("\n"); printSendActions = false; } @@ -477,7 +721,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt else add_exec_stack_entry(s->_executionStack, call.address.func, call.sp, work_obj, call.argc, call.argp, - call.selector, send_obj, origin, SCI_XS_CALLEE_LOCALS); + call.selector, -1, -1, send_obj, origin, SCI_XS_CALLEE_LOCALS); } _exec_varselectors(s); @@ -486,7 +730,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt } static ExecStack *add_exec_stack_varselector(Common::List<ExecStack> &execStack, reg_t objp, int argc, StackPtr argp, Selector selector, const ObjVarRef& address, int origin) { - ExecStack *xstack = add_exec_stack_entry(execStack, NULL_REG, 0, objp, argc, argp, selector, objp, origin, SCI_XS_CALLEE_LOCALS); + ExecStack *xstack = add_exec_stack_entry(execStack, NULL_REG, 0, objp, argc, argp, selector, -1, -1, objp, origin, SCI_XS_CALLEE_LOCALS); // Store selector address in sp xstack->addr.varp = address; @@ -496,7 +740,7 @@ static ExecStack *add_exec_stack_varselector(Common::List<ExecStack> &execStack, } static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t pc, StackPtr sp, reg_t objp, int argc, - StackPtr argp, Selector selector, reg_t sendp, int origin, SegmentId _localsSegment) { + StackPtr argp, Selector selector, int exportId, int localCallOffset, reg_t sendp, int origin, SegmentId _localsSegment) { // Returns new TOS element for the execution stack // _localsSegment may be -1 if derived from the called object @@ -520,8 +764,10 @@ static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t *argp = make_reg(0, argc); // SCI code relies on the zeroeth argument to equal argc // Additional debug information - xstack.selector = selector; - xstack.origin = origin; + xstack.debugSelector = selector; + xstack.debugExportId = exportId; + xstack.debugLocalCallOffset = localCallOffset; + xstack.debugOrigin = origin; xstack.type = EXEC_STACK_TYPE_CALL; // Normal call @@ -529,10 +775,6 @@ static ExecStack *add_exec_stack_entry(Common::List<ExecStack> &execStack, reg_t return &(execStack.back()); } -#ifdef DISABLE_VALIDATIONS -# define kernel_matches_signature(a, b, c, d) 1 -#endif - static reg_t pointer_add(EngineState *s, reg_t base, int offset) { SegmentObj *mobj = s->_segMan->getSegmentObj(base.segment); @@ -560,84 +802,114 @@ static reg_t pointer_add(EngineState *s, reg_t base, int offset) { } } -static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) { - - if (kernelFuncNum >= (int)g_sci->getKernel()->_kernelFuncs.size()) - error("Invalid kernel function 0x%x requested", kernelFuncNum); +static void addKernelCallToExecStack(EngineState *s, int kernelCallNr, int argc, reg_t *argv) { + // Add stack frame to indicate we're executing a callk. + // This is useful in debugger backtraces if this + // kernel function calls a script itself. + ExecStack *xstack; + xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, -1, NULL_REG, + s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS); + xstack->debugSelector = kernelCallNr; + xstack->type = EXEC_STACK_TYPE_KERNEL; +} - const KernelFuncWithSignature &kernelFunc = g_sci->getKernel()->_kernelFuncs[kernelFuncNum]; +static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { + Kernel *kernel = g_sci->getKernel(); - if (kernelFunc.signature - && !g_sci->getKernel()->signatureMatch(kernelFunc.signature, argc, s->xs->sp + 1)) { - error("[VM] Invalid arguments to kernel call %x", kernelFuncNum); - } + if (kernelCallNr >= (int)kernel->_kernelFuncs.size()) + error("Invalid kernel function 0x%x requested", kernelCallNr); + const KernelFunction &kernelCall = kernel->_kernelFuncs[kernelCallNr]; reg_t *argv = s->xs->sp + 1; - if (!kernelFunc.isDummy) { - // Add stack frame to indicate we're executing a callk. - // This is useful in debugger backtraces if this - // kernel function calls a script itself. - ExecStack *xstack; - xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, NULL_REG, - s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS); - xstack->selector = kernelFuncNum; - xstack->type = EXEC_STACK_TYPE_KERNEL; - - //warning("callk %s", kernelFunc.orig_name.c_str()); - - // TODO: SCI2.1 equivalent - if (s->loadFromLauncher >= 0 && ( - (kernelFuncNum == 0x8 && getSciVersion() <= SCI_VERSION_1_1) || // DrawPic - (kernelFuncNum == 0x3d && getSciVersion() == SCI_VERSION_2) // GetSaveDir - //(kernelFuncNum == 0x28 && getSciVersion() == SCI_VERSION_2_1) // AddPlane - )) { - - // A game is being loaded from the launcher, and the game is about to draw something on - // screen, hence all initialization has taken place (i.e. menus have been constructed etc). - // Therefore, inject a kRestoreGame call here, instead of the requested function. - // The restore call is injected here mainly for games which have a menu, as the menu is - // constructed when the game starts and is not reconstructed when a saved game is loaded. - int saveSlot = s->loadFromLauncher; - s->loadFromLauncher = -1; // invalidate slot, so that we don't load again - - if (saveSlot < 0) - error("Requested to load invalid save slot"); // should never happen, really - - reg_t restoreArgv[2] = { NULL_REG, make_reg(0, saveSlot) }; // special call (argv[0] is NULL) - kRestoreGame(s, 2, restoreArgv); - } else { - // Call kernel function - s->r_acc = kernelFunc.fun(s, argc, argv); + if (kernelCall.signature + && !kernel->signatureMatch(kernelCall.signature, argc, argv)) { + // signature mismatch, check if a workaround is available + SciTrackOriginReply originReply; + reg_t workaround; + workaround = trackOriginAndFindWorkaround(0, kernelCall.workarounds, &originReply); + if ((workaround.segment == 0xFFFF) && (workaround.offset == 0xFFFF)) { + kernel->signatureDebug(kernelCall.signature, argc, argv); + error("[VM] k%s[%x]: signature mismatch via method %s::%s (script %d, localCall %x)", kernelCall.name, kernelCallNr, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); } + // FIXME: implement some real workaround type logic - ignore call, still do call etc. + if (workaround.segment == 2) + s->r_acc = make_reg(0, workaround.offset); + if (workaround.segment) + return; + } - // Remove callk stack frame again - s->_executionStack.pop_back(); + + // Call kernel function + if (!kernelCall.subFunctionCount) { + addKernelCallToExecStack(s, kernelCallNr, argc, argv); + s->r_acc = kernelCall.function(s, argc, argv); } else { - Common::String warningMsg = "Dummy function " + kernelFunc.orig_name + - Common::String::printf("[0x%x]", kernelFuncNum) + - " invoked - ignoring. Params: " + - Common::String::printf("%d", argc) + " ("; + // Sub-functions available, check signature and call that one directly + if (argc < 1) + error("[VM] k%s[%x]: no subfunction-id parameter given", kernelCall.name, kernelCallNr); + if (argv[0].segment) + error("[VM] k%s[%x]: given subfunction-id is actually a pointer", kernelCall.name, kernelCallNr); + const uint16 subId = argv[0].toUint16(); + // Skip over subfunction-id + argc--; + argv++; + if (subId >= kernelCall.subFunctionCount) + error("[VM] k%s: subfunction-id %d requested, but not available", kernelCall.name, subId); + const KernelSubFunction &kernelSubCall = kernelCall.subFunctions[subId]; + if (kernelSubCall.signature && !kernel->signatureMatch(kernelSubCall.signature, argc, argv)) { + // Signature mismatch + SciTrackOriginReply originReply; + reg_t workaround; + workaround = trackOriginAndFindWorkaround(0, kernelSubCall.workarounds, &originReply); + if ((workaround.segment == 0xFFFF) && (workaround.offset == 0xFFFF)) { + kernel->signatureDebug(kernelSubCall.signature, argc, argv); + int callNameLen = strlen(kernelCall.name); + if (strncmp(kernelCall.name, kernelSubCall.name, callNameLen) == 0) { + const char *subCallName = kernelSubCall.name + callNameLen; + error("[VM] k%s(%s): signature mismatch via method %s::%s (script %d, localCall %x)", kernelCall.name, subCallName, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); + } + error("[VM] k%s: signature mismatch via method %s::%s (script %d, localCall %x)", kernelSubCall.name, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); + } + // FIXME: implement some real workaround type logic - ignore call, still do call etc. + if (workaround.segment == 2) + s->r_acc = make_reg(0, workaround.offset); + if (workaround.segment) + return; + } + if (!kernelSubCall.function) + error("[VM] k%s: subfunction-id %d requested, but not available", kernelCall.name, subId); + addKernelCallToExecStack(s, kernelCallNr, argc, argv); + s->r_acc = kernelSubCall.function(s, argc, argv); + } + +#if 0 + // Used for debugging + Common::String debugMsg = Common::String::printf("%s [0x%x]", kernelCall.name, kernelCallNr) + + Common::String::printf(", %d params: ", argc) + + " ("; for (int i = 0; i < argc; i++) { - warningMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i])); - warningMsg += (i == argc - 1 ? ")" : ", "); + debugMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i])); + debugMsg += (i == argc - 1 ? ")" : ", "); } - warning("%s", warningMsg.c_str()); - } + debugMsg += ", result: " + Common::String::printf("%04x:%04x", PRINT_REG(s->r_acc)); + debug("%s", debugMsg.c_str()); +#endif + + // Remove callk stack frame again, if there's still an execution stack + if (s->_executionStack.begin() != s->_executionStack.end()) + s->_executionStack.pop_back(); } -static void gc_countdown(EngineState *s) { - if (s->gc_countdown-- <= 0) { - s->gc_countdown = s->script_gc_interval; +static void gcCountDown(EngineState *s) { + if (s->gcCountDown-- <= 0) { + s->gcCountDown = s->scriptGCInterval; run_gc(s); } } -static const byte _fake_return_buffer[2] = {op_ret << 1, op_ret << 1}; - - int readPMachineInstruction(const byte *src, byte &extOpcode, int16 opparams[4]) { uint offset = 0; extOpcode = src[offset++]; // Get "extended" opcode (lower bit has special meaning) @@ -709,50 +981,29 @@ int readPMachineInstruction(const byte *src, byte &extOpcode, int16 opparams[4]) void run_vm(EngineState *s, bool restoring) { assert(s); -#ifndef DISABLE_VALIDATIONS - unsigned int code_buf_size = 0 ; // (Avoid spurious warning) -#endif int temp; - int16 aux_acc; // Auxiliary 16 bit accumulator reg_t r_temp; // Temporary register StackPtr s_temp; // Temporary stack pointer int16 opparams[4]; // opcode parameters - s->restAdjustCur = s->restAdjust; - // &rest adjusts the parameter count by this value + s->restAdjust = 0; // &rest adjusts the parameter count by this value // Current execution data: s->xs = &(s->_executionStack.back()); ExecStack *xs_new = NULL; Object *obj = s->_segMan->getObject(s->xs->objp); + Script *scr = 0; Script *local_script = s->_segMan->getScriptIfLoaded(s->xs->local_segment); - int old_execution_stack_base = s->execution_stack_base; + int old_executionStackBase = s->executionStackBase; // Used to detect the stack bottom, for "physical" returns - const byte *code_buf = NULL; // (Avoid spurious warning) - if (!local_script) { + if (!local_script) error("run_vm(): program counter gone astray (local_script pointer is null)"); - } if (!restoring) - s->execution_stack_base = s->_executionStack.size() - 1; - -#ifndef DISABLE_VALIDATIONS - // Initialize maximum variable count - if (s->script_000->_localsBlock) - s->variables_max[VAR_GLOBAL] = s->script_000->_localsBlock->_locals.size(); - else - s->variables_max[VAR_GLOBAL] = 0; -#endif - - s->variables_seg[VAR_GLOBAL] = s->script_000->_localsSegment; - s->variables_seg[VAR_TEMP] = s->variables_seg[VAR_PARAM] = s->_segMan->findSegmentByType(SEG_TYPE_STACK); - s->variables_base[VAR_TEMP] = s->variables_base[VAR_PARAM] = s->stack_base; + s->executionStackBase = s->_executionStack.size() - 1; - // SCI code reads the zeroth argument to determine argc - if (s->script_000->_localsBlock) - s->variables_base[VAR_GLOBAL] = s->variables[VAR_GLOBAL] = s->script_000->_localsBlock->_locals.begin(); - else - s->variables_base[VAR_GLOBAL] = s->variables[VAR_GLOBAL] = NULL; + s->variablesSegment[VAR_TEMP] = s->variablesSegment[VAR_PARAM] = s->_segMan->findSegmentByType(SEG_TYPE_STACK); + s->variablesBase[VAR_TEMP] = s->variablesBase[VAR_PARAM] = s->stack_base; s->_executionStackPosChanged = true; // Force initialization @@ -760,101 +1011,90 @@ void run_vm(EngineState *s, bool restoring) { int var_type; // See description below int var_number; - g_debugState.old_pc_offset = s->xs->addr.pc.offset; - g_debugState.old_sp = s->xs->sp; + g_sci->_debugState.old_pc_offset = s->xs->addr.pc.offset; + g_sci->_debugState.old_sp = s->xs->sp; + + if (s->abortScriptProcessing != kAbortNone || g_engine->shouldQuit()) + return; // Stop processing if (s->_executionStackPosChanged) { - Script *scr; + scr = s->_segMan->getScriptIfLoaded(s->xs->addr.pc.segment); + if (!scr) + error("No script in segment %d", s->xs->addr.pc.segment); s->xs = &(s->_executionStack.back()); s->_executionStackPosChanged = false; - scr = s->_segMan->getScriptIfLoaded(s->xs->addr.pc.segment); - if (!scr) { - // No script? Implicit return via fake instruction buffer - warning("Running on non-existant script in segment %x", s->xs->addr.pc.segment); - code_buf = _fake_return_buffer; -#ifndef DISABLE_VALIDATIONS - code_buf_size = 2; -#endif - s->xs->addr.pc.offset = 1; - - scr = NULL; - obj = NULL; + obj = s->_segMan->getObject(s->xs->objp); + local_script = s->_segMan->getScriptIfLoaded(s->xs->local_segment); + if (!local_script) { + // FIXME: Why does this happen? Is the script not loaded yet at this point? + warning("Could not find local script from segment %x", s->xs->local_segment); + local_script = NULL; + s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL; + s->variablesMax[VAR_LOCAL] = 0; } else { - obj = s->_segMan->getObject(s->xs->objp); - code_buf = scr->_buf; -#ifndef DISABLE_VALIDATIONS - code_buf_size = scr->getBufSize(); -#endif - local_script = s->_segMan->getScriptIfLoaded(s->xs->local_segment); - if (!local_script) { - warning("Could not find local script from segment %x", s->xs->local_segment); - local_script = NULL; - s->variables_base[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL; -#ifndef DISABLE_VALIDATIONS - s->variables_max[VAR_LOCAL] = 0; -#endif - } else { - - s->variables_seg[VAR_LOCAL] = local_script->_localsSegment; - if (local_script->_localsBlock) - s->variables_base[VAR_LOCAL] = s->variables[VAR_LOCAL] = local_script->_localsBlock->_locals.begin(); - else - s->variables_base[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL; -#ifndef DISABLE_VALIDATIONS - if (local_script->_localsBlock) - s->variables_max[VAR_LOCAL] = local_script->_localsBlock->_locals.size(); - else - s->variables_max[VAR_LOCAL] = 0; - s->variables_max[VAR_TEMP] = s->xs->sp - s->xs->fp; - s->variables_max[VAR_PARAM] = s->xs->argc + 1; -#endif - } - s->variables[VAR_TEMP] = s->xs->fp; - s->variables[VAR_PARAM] = s->xs->variables_argp; + s->variablesSegment[VAR_LOCAL] = local_script->_localsSegment; + if (local_script->_localsBlock) + s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = local_script->_localsBlock->_locals.begin(); + else + s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL; + if (local_script->_localsBlock) + s->variablesMax[VAR_LOCAL] = local_script->_localsBlock->_locals.size(); + else + s->variablesMax[VAR_LOCAL] = 0; + s->variablesMax[VAR_TEMP] = s->xs->sp - s->xs->fp; + s->variablesMax[VAR_PARAM] = s->xs->argc + 1; } - + s->variables[VAR_TEMP] = s->xs->fp; + s->variables[VAR_PARAM] = s->xs->variables_argp; } - if (s->script_abort_flag || g_engine->shouldQuit()) - return; // Emergency + if (s->abortScriptProcessing != kAbortNone || g_engine->shouldQuit()) + return; // Stop processing // Debug if this has been requested: // TODO: re-implement sci_debug_flags - if (g_debugState.debugging /* sci_debug_flags*/) { - script_debug(s); - g_debugState.breakpointWasHit = false; + if (g_sci->_debugState.debugging /* sci_debug_flags*/) { + g_sci->scriptDebug(); + g_sci->_debugState.breakpointWasHit = false; } Console *con = g_sci->getSciDebugger(); if (con->isAttached()) { con->onFrame(); } -#ifndef DISABLE_VALIDATIONS if (s->xs->sp < s->xs->fp) - error("run_vm(): stack underflow, sp: %04x:%04x, fp: %04x:%04x", + error("run_vm(): stack underflow, sp: %04x:%04x, fp: %04x:%04x", PRINT_REG(*s->xs->sp), PRINT_REG(*s->xs->fp)); - s->variables_max[VAR_TEMP] = s->xs->sp - s->xs->fp; + s->variablesMax[VAR_TEMP] = s->xs->sp - s->xs->fp; - if (s->xs->addr.pc.offset >= code_buf_size) - error("run_vm(): program counter gone astray, addr: %d, code buffer size: %d", - s->xs->addr.pc.offset, code_buf_size); -#endif + if (s->xs->addr.pc.offset >= scr->getBufSize()) + error("run_vm(): program counter gone astray, addr: %d, code buffer size: %d", + s->xs->addr.pc.offset, scr->getBufSize()); // Get opcode byte extOpcode; - s->xs->addr.pc.offset += readPMachineInstruction(code_buf + s->xs->addr.pc.offset, extOpcode, opparams); + s->xs->addr.pc.offset += readPMachineInstruction(scr->getBuf() + s->xs->addr.pc.offset, extOpcode, opparams); const byte opcode = extOpcode >> 1; switch (opcode) { case op_bnot: // 0x00 (00) + // Binary not s->r_acc = ACC_ARITHMETIC_L(0xffff ^ /*acc*/); break; case op_add: // 0x01 (01) r_temp = POP32(); + + // Happens in SQ1, room 28, when throwing the water at Orat + if (s->r_acc.segment == 0xFFFF) { + // WORKAROUND: init uninitialized variable to 0 + warning("op_add: attempt to write to uninitialized variable"); + s->r_acc = NULL_REG; + } + if (r_temp.segment || s->r_acc.segment) { reg_t r_ptr = NULL_REG; int offset; @@ -912,23 +1152,23 @@ void run_vm(EngineState *s, bool restoring) { s->r_acc = ACC_ARITHMETIC_L(((int16)POP()) * (int16)/*acc*/); break; - case op_div: // 0x04 (04) - ACC_AUX_LOAD(); - aux_acc = aux_acc != 0 ? ((int16)POP()) / aux_acc : 0; - ACC_AUX_STORE(); + case op_div: { // 0x04 (04) + int16 divisor = signed_validate_arithmetic(s->r_acc); + s->r_acc = make_reg(0, (divisor != 0 ? ((int16)POP()) / divisor : 0)); break; - - case op_mod: // 0x05 (05) - ACC_AUX_LOAD(); - aux_acc = aux_acc != 0 ? ((int16)POP()) % aux_acc : 0; - ACC_AUX_STORE(); + } + case op_mod: { // 0x05 (05) + int16 modulo = signed_validate_arithmetic(s->r_acc); + s->r_acc = make_reg(0, (modulo != 0 ? ((int16)POP()) % modulo : 0)); break; - + } case op_shr: // 0x06 (06) + // Shift right logical s->r_acc = ACC_ARITHMETIC_L(((uint16)POP()) >> /*acc*/); break; case op_shl: // 0x07 (07) + // Shift left logical s->r_acc = ACC_ARITHMETIC_L(((uint16)POP()) << /*acc*/); break; @@ -954,6 +1194,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_eq_: // 0x0d (13) + // == s->r_prev = s->r_acc; r_temp = POP32(); s->r_acc = make_reg(0, r_temp == s->r_acc); @@ -961,6 +1202,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_ne_: // 0x0e (14) + // != s->r_prev = s->r_acc; r_temp = POP32(); s->r_acc = make_reg(0, r_temp != s->r_acc); @@ -968,6 +1210,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_gt_: // 0x0f (15) + // > s->r_prev = s->r_acc; r_temp = POP32(); if (r_temp.segment && s->r_acc.segment) { @@ -975,11 +1218,18 @@ void run_vm(EngineState *s, bool restoring) { if (r_temp.segment != s->r_acc.segment) warning("[VM] Comparing pointers in different segments (%04x:%04x vs. %04x:%04x)", PRINT_REG(r_temp), PRINT_REG(s->r_acc)); s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset > s->r_acc.offset); + } else if (r_temp.segment && !s->r_acc.segment) { + if (s->r_acc.offset >= 1000) + error("[VM] op_gt: comparsion between a pointer and number"); + // Pseudo-WORKAROUND: sierra allows any pointer <-> value comparsion + // Happens in SQ1, room 28, when throwing the water at Orat + s->r_acc = make_reg(0, 1); } else s->r_acc = ACC_ARITHMETIC_L(signed_validate_arithmetic(r_temp) > (int16)/*acc*/); break; case op_ge_: // 0x10 (16) + // >= s->r_prev = s->r_acc; r_temp = POP32(); if (r_temp.segment && s->r_acc.segment) { @@ -991,17 +1241,25 @@ void run_vm(EngineState *s, bool restoring) { break; case op_lt_: // 0x11 (17) + // < s->r_prev = s->r_acc; r_temp = POP32(); if (r_temp.segment && s->r_acc.segment) { if (r_temp.segment != s->r_acc.segment) warning("[VM] Comparing pointers in different segments (%04x:%04x vs. %04x:%04x)", PRINT_REG(r_temp), PRINT_REG(s->r_acc)); s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset < s->r_acc.offset); + } else if (r_temp.segment && !s->r_acc.segment) { + if (s->r_acc.offset >= 1000) + error("[VM] op_lt: comparsion between a pointer and number"); + // Pseudo-WORKAROUND: sierra allows any pointer <-> value comparsion + // Happens in SQ1, room 58, when giving id-card to robot + s->r_acc = make_reg(0, 1); } else s->r_acc = ACC_ARITHMETIC_L(signed_validate_arithmetic(r_temp) < (int16)/*acc*/); break; case op_le_: // 0x12 (18) + // <= s->r_prev = s->r_acc; r_temp = POP32(); if (r_temp.segment && s->r_acc.segment) { @@ -1013,6 +1271,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_ugt_: // 0x13 (19) + // > (unsigned) s->r_prev = s->r_acc; r_temp = POP32(); @@ -1024,8 +1283,8 @@ void run_vm(EngineState *s, bool restoring) { // (Print "foo") // Pointer to a string // (Print 420 5) // Reference to the fifth message in text resource 420 - // It works because in those games, the maximum resource number is 999, - // so any parameter value above that threshold must be a pointer. + // It works because in those games, the maximum resource number is 999, + // so any parameter value above that threshold must be a pointer. if (r_temp.segment && (s->r_acc == make_reg(0, 1000))) s->r_acc = make_reg(0, 1); else if (r_temp.segment && s->r_acc.segment) @@ -1035,6 +1294,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_uge_: // 0x14 (20) + // >= (unsigned) s->r_prev = s->r_acc; r_temp = POP32(); @@ -1048,6 +1308,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_ult_: // 0x15 (21) + // < (unsigned) s->r_prev = s->r_acc; r_temp = POP32(); @@ -1061,6 +1322,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_ule_: // 0x16 (22) + // <= (unsigned) s->r_prev = s->r_acc; r_temp = POP32(); @@ -1074,11 +1336,13 @@ void run_vm(EngineState *s, bool restoring) { break; case op_bt: // 0x17 (23) + // Branch relative if true if (s->r_acc.offset || s->r_acc.segment) s->xs->addr.pc.offset += opparams[0]; break; case op_bnt: // 0x18 (24) + // Branch relative if not true if (!(s->r_acc.offset || s->r_acc.segment)) s->xs->addr.pc.offset += opparams[0]; break; @@ -1088,45 +1352,56 @@ void run_vm(EngineState *s, bool restoring) { break; case op_ldi: // 0x1a (26) + // Load data immediate s->r_acc = make_reg(0, opparams[0]); break; case op_push: // 0x1b (27) + // Push to stack PUSH32(s->r_acc); break; case op_pushi: // 0x1c (28) + // Push immediate PUSH(opparams[0]); break; case op_toss: // 0x1d (29) + // TOS (Top Of Stack) subtract s->xs->sp--; break; case op_dup: // 0x1e (30) + // Duplicate TOD (Top Of Stack) element r_temp = s->xs->sp[-1]; PUSH32(r_temp); break; case op_link: // 0x1f (31) + // We shouldn't initialize temp variables at all + // We put special segment 0xFFFF in there, so that uninitialized reads can get detected for (int i = 0; i < opparams[0]; i++) - s->xs->sp[i] = NULL_REG; + s->xs->sp[i] = make_reg(0xffff, 0); + s->xs->sp += opparams[0]; break; case op_call: { // 0x20 (32) + // Call a script subroutine int argc = (opparams[1] >> 1) // Given as offset, but we need count - + 1 + s->restAdjustCur; + + 1 + s->restAdjust; StackPtr call_base = s->xs->sp - argc; - s->xs->sp[1].offset += s->restAdjustCur; + s->xs->sp[1].offset += s->restAdjust; + + uint16 localCallOffset = s->xs->addr.pc.offset + opparams[0]; xs_new = add_exec_stack_entry(s->_executionStack, make_reg(s->xs->addr.pc.segment, - s->xs->addr.pc.offset + opparams[0]), + localCallOffset), s->xs->sp, s->xs->objp, - (validate_arithmetic(*call_base)) + s->restAdjustCur, - call_base, NULL_SELECTOR, s->xs->objp, + (validate_arithmetic(*call_base)) + s->restAdjust, + call_base, NULL_SELECTOR, -1, localCallOffset, s->xs->objp, s->_executionStack.size()-1, s->xs->local_segment); - s->restAdjustCur = 0; // Used up the &rest adjustment + s->restAdjust = 0; // Used up the &rest adjustment s->xs->sp = call_base; s->_executionStackPosChanged = true; @@ -1134,74 +1409,80 @@ void run_vm(EngineState *s, bool restoring) { } case op_callk: { // 0x21 (33) - gc_countdown(s); + // Call kernel function + gcCountDown(s); s->xs->sp -= (opparams[1] >> 1) + 1; bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); - if (!oldScriptHeader) { - s->xs->sp -= s->restAdjustCur; - s->restAdjust = 0; // We just used up the s->restAdjustCur, remember? - } + if (!oldScriptHeader) + s->xs->sp -= s->restAdjust; int argc = validate_arithmetic(s->xs->sp[0]); if (!oldScriptHeader) - argc += s->restAdjustCur; + argc += s->restAdjust; callKernelFunc(s, opparams[0], argc); if (!oldScriptHeader) - s->restAdjustCur = s->restAdjust; + s->restAdjust = 0; // Calculate xs again: The kernel function might // have spawned a new VM xs_new = &(s->_executionStack.back()); s->_executionStackPosChanged = true; + + // If a game is being loaded, stop processing + if (s->abortScriptProcessing != kAbortNone || g_engine->shouldQuit()) + return; // Stop processing + break; } case op_callb: // 0x22 (34) - temp = ((opparams[1] >> 1) + s->restAdjustCur + 1); + // Call base script + temp = ((opparams[1] >> 1) + s->restAdjust + 1); s_temp = s->xs->sp; s->xs->sp -= temp; - s->xs->sp[0].offset += s->restAdjustCur; + s->xs->sp[0].offset += s->restAdjust; xs_new = execute_method(s, 0, opparams[0], s_temp, s->xs->objp, s->xs->sp[0].offset, s->xs->sp); - s->restAdjustCur = 0; // Used up the &rest adjustment + s->restAdjust = 0; // Used up the &rest adjustment if (xs_new) // in case of error, keep old stack s->_executionStackPosChanged = true; break; case op_calle: // 0x23 (35) - temp = ((opparams[2] >> 1) + s->restAdjustCur + 1); + // Call external script + temp = ((opparams[2] >> 1) + s->restAdjust + 1); s_temp = s->xs->sp; s->xs->sp -= temp; - s->xs->sp[0].offset += s->restAdjustCur; + s->xs->sp[0].offset += s->restAdjust; xs_new = execute_method(s, opparams[0], opparams[1], s_temp, s->xs->objp, s->xs->sp[0].offset, s->xs->sp); - s->restAdjustCur = 0; // Used up the &rest adjustment + s->restAdjust = 0; // Used up the &rest adjustment if (xs_new) // in case of error, keep old stack s->_executionStackPosChanged = true; break; case op_ret: // 0x24 (36) + // Return from an execution loop started by call, calle, callb, send, self or super do { StackPtr old_sp2 = s->xs->sp; StackPtr old_fp = s->xs->fp; ExecStack *old_xs = &(s->_executionStack.back()); - if ((int)s->_executionStack.size() - 1 == s->execution_stack_base) { // Have we reached the base? - s->execution_stack_base = old_execution_stack_base; // Restore stack base + if ((int)s->_executionStack.size() - 1 == s->executionStackBase) { // Have we reached the base? + s->executionStackBase = old_executionStackBase; // Restore stack base s->_executionStack.pop_back(); s->_executionStackPosChanged = true; - s->restAdjust = s->restAdjustCur; // Update &rest return; // "Hard" return } @@ -1233,17 +1514,18 @@ void run_vm(EngineState *s, bool restoring) { break; case op_send: // 0x25 (37) + // Send for one or more selectors s_temp = s->xs->sp; - s->xs->sp -= ((opparams[0] >> 1) + s->restAdjustCur); // Adjust stack + s->xs->sp -= ((opparams[0] >> 1) + s->restAdjust); // Adjust stack - s->xs->sp[1].offset += s->restAdjustCur; + s->xs->sp[1].offset += s->restAdjust; xs_new = send_selector(s, s->r_acc, s->r_acc, s_temp, - (int)(opparams[0] >> 1) + (uint16)s->restAdjustCur, s->xs->sp); + (int)(opparams[0] >> 1) + (uint16)s->restAdjust, s->xs->sp); if (xs_new && xs_new != s->xs) s->_executionStackPosChanged = true; - s->restAdjustCur = 0; + s->restAdjust = 0; break; @@ -1253,6 +1535,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_class: // 0x28 (40) + // Get class address s->r_acc = s->_segMan->getClassAddress((unsigned)opparams[0], SCRIPT_GET_LOCK, s->xs->addr.pc); break; @@ -1262,45 +1545,48 @@ void run_vm(EngineState *s, bool restoring) { break; case op_self: // 0x2a (42) + // Send to self s_temp = s->xs->sp; - s->xs->sp -= ((opparams[0] >> 1) + s->restAdjustCur); // Adjust stack + s->xs->sp -= ((opparams[0] >> 1) + s->restAdjust); // Adjust stack - s->xs->sp[1].offset += s->restAdjustCur; + s->xs->sp[1].offset += s->restAdjust; xs_new = send_selector(s, s->xs->objp, s->xs->objp, - s_temp, (int)(opparams[0] >> 1) + (uint16)s->restAdjustCur, + s_temp, (int)(opparams[0] >> 1) + (uint16)s->restAdjust, s->xs->sp); if (xs_new && xs_new != s->xs) s->_executionStackPosChanged = true; - s->restAdjustCur = 0; + s->restAdjust = 0; break; case op_super: // 0x2b (43) + // Send to any class r_temp = s->_segMan->getClassAddress(opparams[0], SCRIPT_GET_LOAD, s->xs->addr.pc); if (!r_temp.segment) error("[VM]: Invalid superclass in object"); else { s_temp = s->xs->sp; - s->xs->sp -= ((opparams[1] >> 1) + s->restAdjustCur); // Adjust stack + s->xs->sp -= ((opparams[1] >> 1) + s->restAdjust); // Adjust stack - s->xs->sp[1].offset += s->restAdjustCur; + s->xs->sp[1].offset += s->restAdjust; xs_new = send_selector(s, r_temp, s->xs->objp, s_temp, - (int)(opparams[1] >> 1) + (uint16)s->restAdjustCur, + (int)(opparams[1] >> 1) + (uint16)s->restAdjust, s->xs->sp); if (xs_new && xs_new != s->xs) s->_executionStackPosChanged = true; - s->restAdjustCur = 0; + s->restAdjust = 0; } break; case op_rest: // 0x2c (44) + // Pushes all or part of the parameter variable list on the stack temp = (uint16) opparams[0]; // First argument - s->restAdjustCur = MAX<int16>(s->xs->argc - temp + 1, 0); // +1 because temp counts the paramcount while argc doesn't + s->restAdjust = MAX<int16>(s->xs->argc - temp + 1, 0); // +1 because temp counts the paramcount while argc doesn't for (; temp <= s->xs->argc; temp++) PUSH32(s->xs->variables_argp[temp]); @@ -1308,12 +1594,13 @@ void run_vm(EngineState *s, bool restoring) { break; case op_lea: // 0x2d (45) + // Load Effective Address temp = (uint16) opparams[0] >> 1; var_number = temp & 0x03; // Get variable type // Get variable block offset - r_temp.segment = s->variables_seg[var_number]; - r_temp.offset = s->variables[var_number] - s->variables_base[var_number]; + r_temp.segment = s->variablesSegment[var_number]; + r_temp.offset = s->variables[var_number] - s->variablesBase[var_number]; if (temp & 0x08) // Add accumulator offset if requested r_temp.offset += signed_validate_arithmetic(s->r_acc); @@ -1326,6 +1613,7 @@ void run_vm(EngineState *s, bool restoring) { case op_selfID: // 0x2e (46) + // Get 'self' identity s->r_acc = s->xs->objp; break; @@ -1334,66 +1622,60 @@ void run_vm(EngineState *s, bool restoring) { break; case op_pprev: // 0x30 (48) + // Pushes the value of the prev register, set by the last comparison + // bytecode (eq?, lt?, etc.), on the stack PUSH32(s->r_prev); break; case op_pToa: // 0x31 (49) - s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1)); + // Property To Accumulator + s->r_acc = validate_property(obj, (opparams[0] >> 1)); break; case op_aTop: // 0x32 (50) - OBJ_PROPERTY(obj, (opparams[0] >> 1)) = s->r_acc; + // Accumulator To Property + validate_property(obj, (opparams[0] >> 1)) = s->r_acc; break; case op_pTos: // 0x33 (51) - PUSH32(OBJ_PROPERTY(obj, opparams[0] >> 1)); + // Property To Stack + PUSH32(validate_property(obj, opparams[0] >> 1)); break; case op_sTop: // 0x34 (52) - OBJ_PROPERTY(obj, (opparams[0] >> 1)) = POP32(); + // Stack To Property + validate_property(obj, (opparams[0] >> 1)) = POP32(); break; case op_ipToa: // 0x35 (53) - s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1)); - s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1)) = ACC_ARITHMETIC_L(1 + /*acc*/); + // Incement Property and copy To Accumulator + s->r_acc = validate_property(obj, (opparams[0] >> 1)); + s->r_acc = validate_property(obj, (opparams[0] >> 1)) = ACC_ARITHMETIC_L(1 + /*acc*/); break; case op_dpToa: { // 0x36 (54) - s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1)); -#if 0 - // Speed throttling is possible here as well - // although this opens other issues like mud wrestling in lsl5 uses another local variable for delays - Object *var_container = obj; - if (!(obj->getInfoSelector().offset & SCRIPT_INFO_CLASS)) - var_container = s->_segMan->getObject(obj->getSuperClassSelector()); - uint16 varSelector = var_container->getVarSelector(opparams[0] >> 1); -// printf("%X\n", varSelector); -// printf("%s\n", g_sci->getKernel()->getSelectorName(varSelector).c_str()); - if ((varSelector == 0x84) || (varSelector == 0x92))) { - // selectors cycles, cycleCnt from lsl5 hardcoded - uint32 curTime = g_system->getMillis(); - if (s->_lastAnimateTime + 30 > curTime) - break; - s->_lastAnimateTime = curTime; - } -#endif - s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1)) = ACC_ARITHMETIC_L(-1 + /*acc*/); + // Decrement Property and copy To Accumulator + s->r_acc = validate_property(obj, (opparams[0] >> 1)); + s->r_acc = validate_property(obj, (opparams[0] >> 1)) = ACC_ARITHMETIC_L(-1 + /*acc*/); break; } case op_ipTos: // 0x37 (55) - validate_arithmetic(OBJ_PROPERTY(obj, (opparams[0] >> 1))); - temp = ++OBJ_PROPERTY(obj, (opparams[0] >> 1)).offset; + // Increment Property and push to Stack + validate_arithmetic(validate_property(obj, (opparams[0] >> 1))); + temp = ++validate_property(obj, (opparams[0] >> 1)).offset; PUSH(temp); break; case op_dpTos: // 0x38 (56) - validate_arithmetic(OBJ_PROPERTY(obj, (opparams[0] >> 1))); - temp = --OBJ_PROPERTY(obj, (opparams[0] >> 1)).offset; + // Decrement Property and push to Stack + validate_arithmetic(validate_property(obj, (opparams[0] >> 1))); + temp = --validate_property(obj, (opparams[0] >> 1)).offset; PUSH(temp); break; case op_lofsa: // 0x39 (57) + // Load Offset to Accumulator s->r_acc.segment = s->xs->addr.pc.segment; switch (g_sci->_features->detectLofsType()) { @@ -1407,15 +1689,14 @@ void run_vm(EngineState *s, bool restoring) { s->r_acc.offset = s->xs->addr.pc.offset + opparams[0]; } -#ifndef DISABLE_VALIDATIONS - if (s->r_acc.offset >= code_buf_size) { + if (s->r_acc.offset >= scr->getBufSize()) { error("VM: lofsa operation overflowed: %04x:%04x beyond end" - " of script (at %04x)\n", PRINT_REG(s->r_acc), code_buf_size); + " of script (at %04x)\n", PRINT_REG(s->r_acc), scr->getBufSize()); } -#endif break; case op_lofss: // 0x3a (58) + // Load Offset to Stack r_temp.segment = s->xs->addr.pc.segment; switch (g_sci->_features->detectLofsType()) { @@ -1429,12 +1710,10 @@ void run_vm(EngineState *s, bool restoring) { r_temp.offset = s->xs->addr.pc.offset + opparams[0]; } -#ifndef DISABLE_VALIDATIONS - if (r_temp.offset >= code_buf_size) { + if (r_temp.offset >= scr->getBufSize()) { error("VM: lofss operation overflowed: %04x:%04x beyond end" - " of script (at %04x)", PRINT_REG(r_temp), code_buf_size); + " of script (at %04x)", PRINT_REG(r_temp), scr->getBufSize()); } -#endif PUSH32(r_temp); break; @@ -1455,6 +1734,7 @@ void run_vm(EngineState *s, bool restoring) { PUSH32(s->xs->objp); } else { // Debug opcode op_file, skip null-terminated string (file name) + const byte *code_buf = scr->getBuf(); while (code_buf[s->xs->addr.pc.offset++]) ; } break; @@ -1467,42 +1747,49 @@ void run_vm(EngineState *s, bool restoring) { case op_lal: // 0x41 (65) case op_lat: // 0x42 (66) case op_lap: // 0x43 (67) + // Load global, local, temp or param variable into the accumulator var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; - s->r_acc = READ_VAR(var_type, var_number, s->r_acc); + s->r_acc = READ_VAR(var_type, var_number); break; case op_lsg: // 0x44 (68) case op_lsl: // 0x45 (69) case op_lst: // 0x46 (70) case op_lsp: // 0x47 (71) + // Load global, local, temp or param variable into the stack var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; - PUSH32(READ_VAR(var_type, var_number, s->r_acc)); + PUSH32(READ_VAR(var_type, var_number)); break; case op_lagi: // 0x48 (72) case op_lali: // 0x49 (73) case op_lati: // 0x4a (74) case op_lapi: // 0x4b (75) + // Load global, local, temp or param variable into the accumulator, + // using the accumulator as an additional index var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); - s->r_acc = READ_VAR(var_type, var_number, s->r_acc); + s->r_acc = READ_VAR(var_type, var_number); break; case op_lsgi: // 0x4c (76) case op_lsli: // 0x4d (77) case op_lsti: // 0x4e (78) case op_lspi: // 0x4f (79) + // Load global, local, temp or param variable into the stack, + // using the accumulator as an additional index var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); - PUSH32(READ_VAR(var_type, var_number, s->r_acc)); + PUSH32(READ_VAR(var_type, var_number)); break; case op_sag: // 0x50 (80) case op_sal: // 0x51 (81) case op_sat: // 0x52 (82) case op_sap: // 0x53 (83) + // Save the accumulator into the global, local, temp or param variable var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; WRITE_VAR(var_type, var_number, s->r_acc); @@ -1512,6 +1799,7 @@ void run_vm(EngineState *s, bool restoring) { case op_ssl: // 0x55 (85) case op_sst: // 0x56 (86) case op_ssp: // 0x57 (87) + // Save the stack into the global, local, temp or param variable var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; WRITE_VAR(var_type, var_number, POP32()); @@ -1521,6 +1809,9 @@ void run_vm(EngineState *s, bool restoring) { case op_sali: // 0x59 (89) case op_sati: // 0x5a (90) case op_sapi: // 0x5b (91) + // Save the accumulator into the global, local, temp or param variable, + // using the accumulator as an additional index + // Special semantics because it wouldn't really make a whole lot // of sense otherwise, with acc being used for two things // simultaneously... @@ -1534,6 +1825,8 @@ void run_vm(EngineState *s, bool restoring) { case op_ssli: // 0x5d (93) case op_ssti: // 0x5e (94) case op_sspi: // 0x5f (95) + // Save the stack into the global, local, temp or param variable, + // using the accumulator as an additional index var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); WRITE_VAR(var_type, var_number, POP32()); @@ -1543,9 +1836,11 @@ void run_vm(EngineState *s, bool restoring) { case op_plusal: // 0x61 (97) case op_plusat: // 0x62 (98) case op_plusap: // 0x63 (99) + // Increment the global, local, temp or param variable and save it + // to the accumulator var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; - r_temp = READ_VAR(var_type, var_number, s->r_acc); + r_temp = READ_VAR(var_type, var_number); if (r_temp.segment) { // Pointer arithmetics! s->r_acc = pointer_add(s, r_temp, 1); @@ -1558,9 +1853,11 @@ void run_vm(EngineState *s, bool restoring) { case op_plussl: // 0x65 (101) case op_plusst: // 0x66 (102) case op_plussp: // 0x67 (103) + // Increment the global, local, temp or param variable and save it + // to the stack var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; - r_temp = READ_VAR(var_type, var_number, s->r_acc); + r_temp = READ_VAR(var_type, var_number); if (r_temp.segment) { // Pointer arithmetics! r_temp = pointer_add(s, r_temp, 1); @@ -1574,9 +1871,11 @@ void run_vm(EngineState *s, bool restoring) { case op_plusali: // 0x69 (105) case op_plusati: // 0x6a (106) case op_plusapi: // 0x6b (107) + // Increment the global, local, temp or param variable and save it + // to the accumulator, using the accumulator as an additional index var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); - r_temp = READ_VAR(var_type, var_number, s->r_acc); + r_temp = READ_VAR(var_type, var_number); if (r_temp.segment) { // Pointer arithmetics! s->r_acc = pointer_add(s, r_temp, 1); @@ -1589,9 +1888,11 @@ void run_vm(EngineState *s, bool restoring) { case op_plussli: // 0x6d (109) case op_plussti: // 0x6e (110) case op_plusspi: // 0x6f (111) + // Increment the global, local, temp or param variable and save it + // to the stack, using the accumulator as an additional index var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); - r_temp = READ_VAR(var_type, var_number, s->r_acc); + r_temp = READ_VAR(var_type, var_number); if (r_temp.segment) { // Pointer arithmetics! r_temp = pointer_add(s, r_temp, 1); @@ -1605,9 +1906,11 @@ void run_vm(EngineState *s, bool restoring) { case op_minusal: // 0x71 (113) case op_minusat: // 0x72 (114) case op_minusap: // 0x73 (115) + // Decrement the global, local, temp or param variable and save it + // to the accumulator var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; - r_temp = READ_VAR(var_type, var_number, s->r_acc); + r_temp = READ_VAR(var_type, var_number); if (r_temp.segment) { // Pointer arithmetics! s->r_acc = pointer_add(s, r_temp, -1); @@ -1620,9 +1923,11 @@ void run_vm(EngineState *s, bool restoring) { case op_minussl: // 0x75 (117) case op_minusst: // 0x76 (118) case op_minussp: // 0x77 (119) + // Decrement the global, local, temp or param variable and save it + // to the stack var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; - r_temp = READ_VAR(var_type, var_number, s->r_acc); + r_temp = READ_VAR(var_type, var_number); if (r_temp.segment) { // Pointer arithmetics! r_temp = pointer_add(s, r_temp, -1); @@ -1636,9 +1941,11 @@ void run_vm(EngineState *s, bool restoring) { case op_minusali: // 0x79 (121) case op_minusati: // 0x7a (122) case op_minusapi: // 0x7b (123) + // Decrement the global, local, temp or param variable and save it + // to the accumulator, using the accumulator as an additional index var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); - r_temp = READ_VAR(var_type, var_number, s->r_acc); + r_temp = READ_VAR(var_type, var_number); if (r_temp.segment) { // Pointer arithmetics! s->r_acc = pointer_add(s, r_temp, -1); @@ -1651,9 +1958,11 @@ void run_vm(EngineState *s, bool restoring) { case op_minussli: // 0x7d (125) case op_minussti: // 0x7e (126) case op_minusspi: // 0x7f (127) + // Decrement the global, local, temp or param variable and save it + // to the stack, using the accumulator as an additional index var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); - r_temp = READ_VAR(var_type, var_number, s->r_acc); + r_temp = READ_VAR(var_type, var_number); if (r_temp.segment) { // Pointer arithmetics! r_temp = pointer_add(s, r_temp, -1); @@ -1671,100 +1980,15 @@ void run_vm(EngineState *s, bool restoring) { if (s->_executionStackPosChanged) // Force initialization s->xs = xs_new; -//#ifndef DISABLE_VALIDATIONS if (s->xs != &(s->_executionStack.back())) { - warning("xs is stale (%p vs %p); last command was %02x", + error("xs is stale (%p vs %p); last command was %02x", (void *)s->xs, (void *)&(s->_executionStack.back()), opcode); } -//#endif - ++s->script_step_counter; + ++s->scriptStepCounter; } } -static void _init_stack_base_with_selector(EngineState *s, Selector selector) { - s->stack_base[0] = make_reg(0, (uint16)selector); - s->stack_base[1] = NULL_REG; -} - -static EngineState *_game_run(EngineState *&s) { - bool restoring = false; - - if (DebugMan.isDebugChannelEnabled(kDebugLevelOnStartup)) - g_sci->getSciDebugger()->attach(); - - do { - s->_executionStackPosChanged = false; - run_vm(s, restoring); - if (s->restarting_flags & SCI_GAME_IS_RESTARTING_NOW) { // Restart was requested? - restoring = false; - s->_executionStack.clear(); - s->_executionStackPosChanged = false; - - game_exit(s); - script_init_engine(s); - game_init(s); -#ifdef USE_OLD_MUSIC_FUNCTIONS - s->_sound.sfx_reset_player(); -#endif - _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.play); - - send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base); - - s->script_abort_flag = 0; - s->restarting_flags = SCI_GAME_WAS_RESTARTED; - - } else { - restoring = s->restoring; - if (restoring) { - game_exit(s); - s->restoring = false; - if (s->script_abort_flag == 2) { - debugC(2, kDebugLevelVM, "Restarting with replay()"); - s->_executionStack.clear(); // Restart with replay - - _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.replay); - - send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base); - } - - s->script_abort_flag = 0; - - } else - break; // exit loop - } - } while (true); - - return s; -} - -int game_run(EngineState **_s) { - EngineState *s = *_s; - - debugC(2, kDebugLevelVM, "Calling %s::play()", g_sci->getGameID()); - _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.play); // Call the play selector - - // Now: Register the first element on the execution stack- - if (!send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base)) { - Console *con = g_sci->getSciDebugger(); - con->printObject(s->_gameObj); - warning("Failed to run the game! Aborting..."); - return 1; - } - // and ENGAGE! - _game_run(*_s); - - debugC(2, kDebugLevelVM, "Game::play() finished."); - - return 0; -} - -void quit_vm(EngineState *s) { - s->script_abort_flag = 1; // Terminate VM - g_debugState.seeking = kDebugSeekNothing; - g_debugState.runningStep = 0; -} - reg_t *ObjVarRef::getPointer(SegManager *segMan) const { Object *o = segMan->getObject(obj); return o ? &o->getVariableRef(varindex) : 0; diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 67a6bd0dc3..81ec4f1c61 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -49,11 +49,6 @@ class ResourceManager; /** Offset of this identifier */ #define SCRIPT_OBJECT_MAGIC_OFFSET (getSciVersion() < SCI_VERSION_1_1 ? -8 : 0) -/** Script-relative offset of the species ID */ -#define SCRIPT_SPECIES_OFFSET 8 -8 - -#define SCRIPT_SUPERCLASS_OFFSET (getSciVersion() < SCI_VERSION_1_1 ? 10 -8 : 12) - /** Stack pointer value: Use predecessor's value */ #define CALL_SP_CARRY NULL @@ -69,115 +64,7 @@ struct Class { reg_t reg; ///< offset; script-relative offset, segment: 0 if not instantiated }; -#define RAW_IS_OBJECT(datablock) (READ_SCI11ENDIAN_UINT16(((byte *) datablock) + SCRIPT_OBJECT_MAGIC_OFFSET) == SCRIPT_OBJECT_MAGIC_NUMBER) - -/** Contains selector IDs for a few selected selectors */ -struct SelectorCache { - SelectorCache() { - memset(this, 0, sizeof(*this)); - } - - // Statically defined selectors, (almost the) same in all SCI versions - Selector y; - Selector x; - Selector view, loop, cel; ///< Description of a specific image - Selector underBits; ///< Used by the graphics subroutines to store backupped BG pic data - Selector nsTop, nsLeft, nsBottom, nsRight; ///< View boundaries ('now seen') - Selector lsTop, lsLeft, lsBottom, lsRight; ///< Used by Animate() subfunctions and scroll list controls - Selector signal; ///< Used by Animate() to control a view's behaviour - Selector illegalBits; ///< Used by CanBeHere - Selector brTop, brLeft, brBottom, brRight; ///< Bounding Rectangle - // name, key, time - Selector text; ///< Used by controls - Selector elements; ///< Used by SetSynonyms() - // color, back - Selector mode; ///< Used by text controls (-> DrawControl()) - // style - Selector state, font, type;///< Used by controls - // window - Selector cursor, max; ///< Used by EditControl - // mark, who - Selector message; ///< Used by GetEvent - // edit - Selector play; ///< Play function (first function to be called) - Selector number; - Selector handle; ///< Replaced by nodePtr in SCI1+ - Selector nodePtr; ///< Replaces handle in SCI1+ - Selector client; ///< The object that wants to be moved - Selector dx, dy; ///< Deltas - Selector b_movCnt, b_i1, b_i2, b_di, b_xAxis, b_incr; ///< Various Bresenham vars - Selector xStep, yStep; ///< BR adjustments - Selector moveSpeed; ///< Used for DoBresen - Selector canBeHere; ///< Funcselector: Checks for movement validity in SCI0 - Selector heading, mover; ///< Used in DoAvoider - Selector doit; ///< Called (!) by the Animate() system call - Selector isBlocked, looper; ///< Used in DoAvoider - Selector priority; - Selector modifiers; ///< Used by GetEvent - Selector replay; ///< Replay function - // setPri, at, next, done, width - Selector wordFail, syntaxFail; ///< Used by Parse() - // semanticFail, pragmaFail - // said - Selector claimed; ///< Used generally by the event mechanism - // value, save, restore, title, button, icon, draw - Selector delete_; ///< Called by Animate() to dispose a view object - Selector z; - - // SCI1+ static selectors - Selector parseLang; - Selector printLang; ///< Used for i18n - Selector subtitleLang; - Selector size; - Selector points; ///< Used by AvoidPath() - Selector palette; - Selector dataInc; - // handle (in SCI1) - Selector min; ///< SMPTE time format - Selector sec; - Selector frame; - Selector vol; - Selector pri; - // perform - Selector moveDone; ///< used for DoBresen - - // SCI1 selectors which have been moved a bit in SCI1.1, but otherwise static - Selector cantBeHere; ///< Checks for movement avoidance in SCI1+. Replaces canBeHere - Selector topString; ///< SCI1 scroll lists use this instead of lsTop - Selector flags; - - // SCI1+ audio sync related selectors, not static. They're used for lip syncing in - // CD talkie games - Selector syncCue; ///< Used by DoSync() - Selector syncTime; - - // SCI1.1 specific selectors - Selector scaleSignal; // < Used by Animate() for cel scaling (SCI1.1+) - Selector scaleX, scaleY; ///< SCI1.1 view scaling - - // Used for auto detection purposes - Selector overlay; ///< Used to determine if a game is using old gfx functions or not - - // SCI1.1 Mac icon bar selectors - Selector iconIndex; ///< Used to index icon bar objects - -#ifdef ENABLE_SCI32 - Selector data; // Used by Array()/String() - Selector picture; // Used to hold the picture ID for SCI32 pictures - - Selector plane; - Selector top; - Selector left; - Selector bottom; - Selector right; - Selector resX; - Selector resY; - - Selector fore; - Selector back; - Selector dimmed; -#endif -}; +#define RAW_IS_OBJECT(datablock) (READ_SCI11ENDIAN_UINT16(((const byte *) datablock) + SCRIPT_OBJECT_MAGIC_OFFSET) == SCRIPT_OBJECT_MAGIC_NUMBER) // A reference to an object's variable. // The object is stored as a reg_t, the variable as an index into _variables @@ -210,8 +97,10 @@ struct ExecStack { StackPtr variables_argp; // Argument pointer SegmentId local_segment; // local variables etc - Selector selector; // The selector which was used to call or -1 if not applicable - int origin; // The stack frame position the call was made from, or -1 if it was the initial call + Selector debugSelector; // The selector which was used to call or -1 if not applicable + int debugExportId; // The exportId which was called or -1 if not applicable + int debugLocalCallOffset; // Local call offset or -1 if not applicable + int debugOrigin; // The stack frame position the call was made from, or -1 if it was the initial call ExecStackType type; reg_t* getVarPointer(SegManager *segMan) const; @@ -229,6 +118,160 @@ enum { GC_INTERVAL = 32768 }; +// Opcode formats +enum opcode_format { + Script_Invalid = -1, + Script_None = 0, + Script_Byte, + Script_SByte, + Script_Word, + Script_SWord, + Script_Variable, + Script_SVariable, + Script_SRelative, + Script_Property, + Script_Global, + Script_Local, + Script_Temp, + Script_Param, + Script_Offset, + Script_End +}; + +enum sci_opcodes { + op_bnot = 0x00, // 000 + op_add = 0x01, // 001 + op_sub = 0x02, // 002 + op_mul = 0x03, // 003 + op_div = 0x04, // 004 + op_mod = 0x05, // 005 + op_shr = 0x06, // 006 + op_shl = 0x07, // 007 + op_xor = 0x08, // 008 + op_and = 0x09, // 009 + op_or = 0x0a, // 010 + op_neg = 0x0b, // 011 + op_not = 0x0c, // 012 + op_eq_ = 0x0d, // 013 + op_ne_ = 0x0e, // 014 + op_gt_ = 0x0f, // 015 + op_ge_ = 0x10, // 016 + op_lt_ = 0x11, // 017 + op_le_ = 0x12, // 018 + op_ugt_ = 0x13, // 019 + op_uge_ = 0x14, // 020 + op_ult_ = 0x15, // 021 + op_ule_ = 0x16, // 022 + op_bt = 0x17, // 023 + op_bnt = 0x18, // 024 + op_jmp = 0x19, // 025 + op_ldi = 0x1a, // 026 + op_push = 0x1b, // 027 + op_pushi = 0x1c, // 028 + op_toss = 0x1d, // 029 + op_dup = 0x1e, // 030 + op_link = 0x1f, // 031 + op_call = 0x20, // 032 + op_callk = 0x21, // 033 + op_callb = 0x22, // 034 + op_calle = 0x23, // 035 + op_ret = 0x24, // 036 + op_send = 0x25, // 037 + // dummy 0x26, // 038 + // dummy 0x27, // 039 + op_class = 0x28, // 040 + // dummy 0x29, // 041 + op_self = 0x2a, // 042 + op_super = 0x2b, // 043 + op_rest = 0x2c, // 044 + op_lea = 0x2d, // 045 + op_selfID = 0x2e, // 046 + // dummy 0x2f // 047 + op_pprev = 0x30, // 048 + op_pToa = 0x31, // 049 + op_aTop = 0x32, // 050 + op_pTos = 0x33, // 051 + op_sTop = 0x34, // 052 + op_ipToa = 0x35, // 053 + op_dpToa = 0x36, // 054 + op_ipTos = 0x37, // 055 + op_dpTos = 0x38, // 056 + op_lofsa = 0x39, // 057 + op_lofss = 0x3a, // 058 + op_push0 = 0x3b, // 059 + op_push1 = 0x3c, // 060 + op_push2 = 0x3d, // 061 + op_pushSelf = 0x3e, // 062 + op_line = 0x3f, // 063 + op_lag = 0x40, // 064 + op_lal = 0x41, // 065 + op_lat = 0x42, // 066 + op_lap = 0x43, // 067 + op_lsg = 0x44, // 068 + op_lsl = 0x45, // 069 + op_lst = 0x46, // 070 + op_lsp = 0x47, // 071 + op_lagi = 0x48, // 072 + op_lali = 0x49, // 073 + op_lati = 0x4a, // 074 + op_lapi = 0x4b, // 075 + op_lsgi = 0x4c, // 076 + op_lsli = 0x4d, // 077 + op_lsti = 0x4e, // 078 + op_lspi = 0x4f, // 079 + op_sag = 0x50, // 080 + op_sal = 0x51, // 081 + op_sat = 0x52, // 082 + op_sap = 0x53, // 083 + op_ssg = 0x54, // 084 + op_ssl = 0x55, // 085 + op_sst = 0x56, // 086 + op_ssp = 0x57, // 087 + op_sagi = 0x58, // 088 + op_sali = 0x59, // 089 + op_sati = 0x5a, // 090 + op_sapi = 0x5b, // 091 + op_ssgi = 0x5c, // 092 + op_ssli = 0x5d, // 093 + op_ssti = 0x5e, // 094 + op_sspi = 0x5f, // 095 + op_plusag = 0x60, // 096 + op_plusal = 0x61, // 097 + op_plusat = 0x62, // 098 + op_plusap = 0x63, // 099 + op_plussg = 0x64, // 100 + op_plussl = 0x65, // 101 + op_plusst = 0x66, // 102 + op_plussp = 0x67, // 103 + op_plusagi = 0x68, // 104 + op_plusali = 0x69, // 105 + op_plusati = 0x6a, // 106 + op_plusapi = 0x6b, // 107 + op_plussgi = 0x6c, // 108 + op_plussli = 0x6d, // 109 + op_plussti = 0x6e, // 110 + op_plusspi = 0x6f, // 111 + op_minusag = 0x70, // 112 + op_minusal = 0x71, // 113 + op_minusat = 0x72, // 114 + op_minusap = 0x73, // 115 + op_minussg = 0x74, // 116 + op_minussl = 0x75, // 117 + op_minusst = 0x76, // 118 + op_minussp = 0x77, // 119 + op_minusagi = 0x78, // 120 + op_minusali = 0x79, // 121 + op_minusati = 0x7a, // 122 + op_minusapi = 0x7b, // 123 + op_minussgi = 0x7c, // 124 + op_minussli = 0x7d, // 125 + op_minussti = 0x7e, // 126 + op_minusspi = 0x7f // 127 +}; + +extern opcode_format g_opcode_formats[128][4]; + +void script_adjust_opcode_formats(); /** * Executes function pubfunct of the specified script. @@ -283,14 +326,6 @@ void run_vm(EngineState *s, bool restoring); void script_debug(EngineState *s); /** - * Initializes a EngineState block - * @param[in] s The state to initialize - * @return 0 on success, 1 if vocab.996 (the class table) is missing - * or corrupted - */ -int script_init_engine(EngineState *); - -/** * Looks up a selector and returns its type and value * varindex is written to iff it is non-NULL and the selector indicates a property of the object. * @param[in] segMan The Segment Manager @@ -314,95 +349,6 @@ SelectorType lookupSelector(SegManager *segMan, reg_t obj, Selector selectorid, ObjVarRef *varp, reg_t *fptr); /** - * Makes sure that a script and its superclasses get loaded to the heap. - * If the script already has been loaded, only the number of lockers is - * increased. All scripts containing superclasses of this script are loaded - * recursively as well, unless 'recursive' is set to zero. The - * complementary function is "script_uninstantiate()" below. - * @param[in] resMan The resource manager - * @param[in] segMan The segment manager - * @param[in] script_nr The script number to load - * @return The script's segment ID or 0 if out of heap - */ -int script_instantiate(ResourceManager *resMan, SegManager *segMan, int script_nr); - -/** - * Decreases the numer of lockers of a script and unloads it if that number - * reaches zero. - * This function will recursively unload scripts containing its - * superclasses, if those aren't locked by other scripts as well. - * @param[in] segMan The segment manager - * @param[in] version The SCI version to use - * @param[in] script_nr The script number that is requestet to be unloaded - */ -void script_uninstantiate(SegManager *segMan, int script_nr); - -/** - * Converts the builtin Sierra game IDs to the ones we use in ScummVM - * @param[in] gameId The internal game ID - * @param[in] gameFlags The game's flags, which are adjusted accordingly for demos - * @return The equivalent ScummVM game id - */ -Common::String convertSierraGameId(const char *gameId, uint32 *gameFlags, ResourceManager *resMan); - -/** - * Initializes an SCI game - * This function must be run before script_run() is executed. Graphics data - * is initialized iff s->gfx_state != NULL. - * @param[in] s The state to operate on - * @return 0 on success, 1 if an error occured. - */ -int game_init(EngineState *s); - -#ifdef USE_OLD_MUSIC_FUNCTIONS -/** - * Initializes the sound part of an SCI game - * This function may only be called if game_init() did not initialize - * the sound data. - * @param[in] s The state to initialize the sound in - * @param[in] sound_flags Flags to pass to the sound subsystem - * @param[in] soundVersion sound-version that got detected during game init - * @return 0 on success, 1 if an error occured - */ -int game_init_sound(EngineState *s, int sound_flags, SciVersion soundVersion); -#endif - -/** - * Runs an SCI game - * This is the main function for SCI games. It takes a valid state, loads - * script 0 to it, finds the game object, allocates a stack, and runs the - * init method of the game object. In layman's terms, this runs an SCI game. - * Note that, EngineState *s may be changed during the game, e.g. if a game - * state is restored. - * @param[in] s Pointer to the pointer of the state to operate on - * @return 0 on success, 1 if an error occured. - */ -int game_run(EngineState **s); - -/** - * Restores an SCI game state and runs the game - * This restores a savegame; otherwise, it behaves just like game_run(). - * @param[in] s Pointer to the pointer of the state to - * operate on - * @param[in] savegame_name Name of the savegame to restore - * @return 0 on success, 1 if an error occured. - */ -int game_restore(EngineState **s, char *savegame_name); - -/** - * Uninitializes an initialized SCI game - * This function should be run after each script_run() call. - * @param[in] s The state to operate on - * @return 0 on success, 1 if an error occured. - */ -int game_exit(EngineState *s); - -/** - * Instructs the virtual machine to abort - */ -void quit_vm(EngineState *s); - -/** * Read a PMachine instruction from a memory buffer and return its length. * * @param[in] src address from which to start parsing diff --git a/engines/sci/engine/vm_types.h b/engines/sci/engine/vm_types.h index 29dc798c35..828fba3d7d 100644 --- a/engines/sci/engine/vm_types.h +++ b/engines/sci/engine/vm_types.h @@ -27,6 +27,7 @@ #define SCI_ENGINE_VM_TYPES_H #include "common/scummsys.h" +#include "common/serializer.h" namespace Sci { @@ -56,6 +57,11 @@ struct reg_t { int16 toSint16() const { return (int16) offset; } + + void saveLoadWithSerializer(Common::Serializer &s) { + s.syncAsUint16LE(segment); + s.syncAsUint16LE(offset); + } }; static inline reg_t make_reg(SegmentId segment, uint16 offset) { @@ -81,6 +87,7 @@ enum { extern const reg_t NULL_REG; extern const reg_t SIGNAL_REG; +extern const reg_t TRUE_REG; // Selector ID typedef int Selector; diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index c3be22b143..a100dda27c 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -25,6 +25,7 @@ #include "common/system.h" #include "common/events.h" +#include "common/file.h" #include "sci/sci.h" #include "sci/event.h" @@ -34,33 +35,51 @@ namespace Sci { -#define SCANCODE_ROWS_NR 3 +EventManager::EventManager(bool fontIsExtended) : _fontIsExtended(fontIsExtended), _modifierStates(0) { -SciEvent::SciEvent(ResourceManager *resMan) { - // Check, if font of current game includes extended chars - _fontIsExtended = resMan->detectFontExtended(); + if (getSciVersion() >= SCI_VERSION_1_MIDDLE) { + _usesNewKeyboardDirectionType = true; + } else if (getSciVersion() <= SCI_VERSION_01) { + _usesNewKeyboardDirectionType = false; + } else { + // they changed this somewhere inbetween SCI1EGA/EARLY + _usesNewKeyboardDirectionType = false; + + // We are looking if script 933 exists, that one has the PseudoMouse class in it that handles it + // The good thing is that PseudoMouse seems to only exists in games that use the new method + if (g_sci->getResMan()->testResource(ResourceId(kResourceTypeScript, 933))) + _usesNewKeyboardDirectionType = true; + // Checking the keyboard driver size in here would also be a valid method, but the driver is only available + // in PC versions of the game + } +} + +EventManager::~EventManager() { } -SciEvent::~SciEvent() { +bool EventManager::getUsesNewKeyboardDirectionType() { + return _usesNewKeyboardDirectionType; } -struct scancode_row { +struct ScancodeRow { int offset; const char *keys; -} scancode_rows[SCANCODE_ROWS_NR] = { +}; + +static const ScancodeRow s_scancodeRows[] = { {0x10, "QWERTYUIOP[]"}, {0x1e, "ASDFGHJKL;'\\"}, {0x2c, "ZXCVBNM,./"} }; -int SciEvent::altify (int ch) { +static int altify(int ch) { // Calculates a PC keyboard scancode from a character */ int row; int c = toupper((char)ch); - for (row = 0; row < SCANCODE_ROWS_NR; row++) { - const char *keys = scancode_rows[row].keys; - int offset = scancode_rows[row].offset; + for (row = 0; row < ARRAYSIZE(s_scancodeRows); row++) { + const char *keys = s_scancodeRows[row].keys; + int offset = s_scancodeRows[row].offset; while (*keys) { if (*keys == c) @@ -74,7 +93,8 @@ int SciEvent::altify (int ch) { return ch; } -int SciEvent::numlockify (int c) { +/* +static int numlockify(int c) { switch (c) { case SCI_KEY_DELETE: return '.'; @@ -102,6 +122,7 @@ int SciEvent::numlockify (int c) { return c; // Unchanged } } +*/ static const byte codepagemap_88591toDOS[0x80] = { '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', // 0x8x @@ -114,9 +135,8 @@ static const byte codepagemap_88591toDOS[0x80] = { '?', 0xa4, 0x95, 0xa2, 0x93, '?', 0x94, '?', '?', 0x97, 0xa3, 0x96, 0x81, '?', '?', 0x98 // 0xFx }; -sciEvent SciEvent::getFromScummVM() { - static int _modifierStates = 0; // FIXME: Avoid non-const global vars - sciEvent input = { SCI_EVENT_NONE, 0, 0, 0 }; +SciEvent EventManager::getScummVMEvent() { + SciEvent input = { SCI_EVENT_NONE, 0, 0, 0 }; Common::EventManager *em = g_system->getEventManager(); Common::Event ev; @@ -315,22 +335,26 @@ sciEvent SciEvent::getFromScummVM() { return input; } -sciEvent SciEvent::get(unsigned int mask) { +SciEvent EventManager::getSciEvent(unsigned int mask) { //sci_event_t error_event = { SCI_EVT_ERROR, 0, 0, 0 }; - sciEvent event = { 0, 0, 0, 0 }; + SciEvent event = { 0, 0, 0, 0 }; - // Update the screen here, since it's called very often - g_system->updateScreen(); + // Update the screen here, since it's called very often. + // Throttle the screen update rate to 60fps. + if (g_system->getMillis() - g_sci->getEngineState()->_screenUpdateTime >= 1000 / 60) { + g_system->updateScreen(); + g_sci->getEngineState()->_screenUpdateTime = g_system->getMillis(); + } // Get all queued events from graphics driver do { - event = getFromScummVM(); + event = getScummVMEvent(); if (event.type != SCI_EVENT_NONE) _events.push_back(event); } while (event.type != SCI_EVENT_NONE); // Search for matching event in queue - Common::List<sciEvent>::iterator iter = _events.begin(); + Common::List<SciEvent>::iterator iter = _events.begin(); while (iter != _events.end() && !((*iter).type & mask)) ++iter; @@ -380,13 +404,13 @@ sciEvent SciEvent::get(unsigned int mask) { return event; } -void SciEvent::sleep(uint32 msecs) { +void SciEngine::sleep(uint32 msecs) { uint32 time; const uint32 wakeup_time = g_system->getMillis() + msecs; while (true) { // let backend process events and update the screen - get(SCI_EVENT_PEEK); + _eventMan->getSciEvent(SCI_EVENT_PEEK); time = g_system->getMillis(); if (time + 10 < wakeup_time) { g_system->delayMillis(10); diff --git a/engines/sci/event.h b/engines/sci/event.h index 9301b1ca09..30098b0f6e 100644 --- a/engines/sci/event.h +++ b/engines/sci/event.h @@ -23,31 +23,29 @@ * */ -#ifndef SCI_ENGINE_EVENT_H -#define SCI_ENGINE_EVENT_H +#ifndef SCI_EVENT_H +#define SCI_EVENT_H #include "common/list.h" namespace Sci { -#define SCI_INPUT_DEFAULT_CLOCKTIME 100000 -#define SCI_INPUT_DEFAULT_REDRAWTIME 30000 - - -struct sciEvent { +struct SciEvent { short type; short data; short modifiers; - short character; /* for keyboard events: 'data' after applying - ** the effects of 'modifiers', e.g. if - ** type == SCI_EVT_KEYBOARD - ** data == 'a' - ** buckybits == SCI_EVM_LSHIFT - ** then - ** character == 'A' - ** For 'Alt', characters are interpreted by their - ** PC keyboard scancodes. - */ + /** + * For keyboard events: 'data' after applying + * the effects of 'modifiers', e.g. if + * type == SCI_EVT_KEYBOARD + * data == 'a' + * buckybits == SCI_EVM_LSHIFT + * then + * character == 'A' + * For 'Alt', characters are interpreted by their + * PC keyboard scancodes. + */ + short character; }; /*Values for type*/ @@ -55,7 +53,7 @@ struct sciEvent { #define SCI_EVENT_MOUSE_PRESS (1<<0) #define SCI_EVENT_MOUSE_RELEASE (1<<1) #define SCI_EVENT_KEYBOARD (1<<2) -#define SCI_EVENT_JOYSTICK (1<<6) +#define SCI_EVENT_DIRECTION (1<<6) #define SCI_EVENT_SAID (1<<7) /*Fake values for other events*/ #define SCI_EVENT_ERROR (1<<10) @@ -111,25 +109,22 @@ struct sciEvent { #define SCI_KEYMOD_NO_FOOLOCK (~(SCI_KEYMOD_SCRLOCK | SCI_KEYMOD_NUMLOCK | SCI_KEYMOD_CAPSLOCK | SCI_KEYMOD_INSERT)) #define SCI_KEYMOD_ALL 0xFF -class SciEvent { +class EventManager { public: - SciEvent(ResourceManager *resMgr); - ~SciEvent(); - - sciEvent get(unsigned int mask); + EventManager(bool fontIsExtended); + ~EventManager(); - void sleep(uint32 msecs); + SciEvent getSciEvent(unsigned int mask); + bool getUsesNewKeyboardDirectionType(); private: - int altify (int ch); - int shiftify (int c); - int numlockify (int c); - sciEvent getFromScummVM(); + SciEvent getScummVMEvent(); - ResourceManager *_resMan; + const bool _fontIsExtended; + int _modifierStates; + Common::List<SciEvent> _events; - bool _fontIsExtended; - Common::List<sciEvent> _events; + bool _usesNewKeyboardDirectionType; }; } // End of namespace Sci diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index c201b2cfb7..6fb427500d 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -28,6 +28,7 @@ #include "graphics/primitives.h" #include "sci/sci.h" +#include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/engine/vm.h" @@ -35,6 +36,7 @@ #include "sci/graphics/cursor.h" #include "sci/graphics/ports.h" #include "sci/graphics/paint16.h" +#include "sci/graphics/palette.h" #include "sci/graphics/view.h" #include "sci/graphics/screen.h" #include "sci/graphics/transitions.h" @@ -48,28 +50,25 @@ GfxAnimate::GfxAnimate(EngineState *state, GfxCache *cache, GfxPorts *ports, Gfx } GfxAnimate::~GfxAnimate() { - free(_listData); - free(_lastCastData); } void GfxAnimate::init() { - _listData = NULL; - _listCount = 0; - _lastCastData = NULL; - _lastCastCount = 0; + _lastCastData.clear(); _ignoreFastCast = false; // fastCast object is not found in any SCI games prior SCI1 if (getSciVersion() <= SCI_VERSION_01) _ignoreFastCast = true; // Also if fastCast object exists at gamestartup, we can assume that the interpreter doesnt do kAnimate aborts - // (found in larry 1) - if (!_s->_segMan->findObjectByName("fastCast").isNull()) - _ignoreFastCast = true; + // (found in Larry 1) + if (getSciVersion() > SCI_VERSION_0_EARLY) { + if (!_s->_segMan->findObjectByName("fastCast").isNull()) + _ignoreFastCast = true; + } } void GfxAnimate::disposeLastCast() { - _lastCastCount = 0; + _lastCastData.clear(); } bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) { @@ -84,10 +83,8 @@ bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) { if (!_ignoreFastCast) { // Check if the game has a fastCast object set // if we don't abort kAnimate processing, at least in kq5 there will be animation cels drawn into speech boxes. - reg_t global84 = _s->script_000->_localsBlock->_locals[84]; - - if (!global84.isNull()) { - if (!strcmp(_s->_segMan->getObjectName(global84), "fastCast")) + if (!_s->variables[VAR_GLOBAL][84].isNull()) { + if (!strcmp(_s->_segMan->getObjectName(_s->variables[VAR_GLOBAL][84]), "fastCast")) return false; } } @@ -95,7 +92,12 @@ bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) { signal = readSelectorValue(_s->_segMan, curObject, SELECTOR(signal)); if (!(signal & kSignalFrozen)) { // Call .doit method of that object - invokeSelector(_s, curObject, g_sci->getKernel()->_selectorCache.doit, kContinueOnInvalidSelector, argc, argv, 0); + invokeSelector(_s, curObject, SELECTOR(doit), argc, argv, 0); + + // If a game is being loaded, stop processing + if (_s->abortScriptProcessing != kAbortNone || g_engine->shouldQuit()) + return true; // Stop processing + // Lookup node again, since the nodetable it was in may have been reallocated curNode = _s->_segMan->lookupNode(curAddress); } @@ -108,99 +110,64 @@ bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) { return true; } -bool sortHelper(const AnimateEntry* entry1, const AnimateEntry* entry2) { - if (entry1->y == entry2->y) { +bool sortHelper(const AnimateEntry &entry1, const AnimateEntry &entry2) { + if (entry1.y == entry2.y) { // if both y and z are the same, use the order we were given originally // this is needed for special cases like iceman room 35 - if (entry1->z == entry2->z) - return entry1->givenOrderNo < entry2->givenOrderNo; + if (entry1.z == entry2.z) + return entry1.givenOrderNo < entry2.givenOrderNo; else - return entry1->z < entry2->z; + return entry1.z < entry2.z; } - return entry1->y < entry2->y; + return entry1.y < entry2.y; } void GfxAnimate::makeSortedList(List *list) { reg_t curAddress = list->first; Node *curNode = _s->_segMan->lookupNode(curAddress); - reg_t curObject; - AnimateEntry *listEntry; - int16 listNr, listCount = 0; - - // Count the list entries - while (curNode) { - listCount++; - curAddress = curNode->succ; - curNode = _s->_segMan->lookupNode(curAddress); - } + int16 listNr; + // Clear lists _list.clear(); - - // No entries -> exit immediately - if (listCount == 0) - return; - - // Adjust list size, if needed - if ((_listData == NULL) || (_listCount < listCount)) { - free(_listData); - _listData = (AnimateEntry *)malloc(listCount * sizeof(AnimateEntry)); - if (!_listData) - error("Could not allocate memory for _listData"); - _listCount = listCount; - - free(_lastCastData); - _lastCastData = (AnimateEntry *)malloc(listCount * sizeof(AnimateEntry)); - if (!_lastCastData) - error("Could not allocate memory for _lastCastData"); - _lastCastCount = 0; - } + _lastCastData.clear(); // Fill the list - curAddress = list->first; - curNode = _s->_segMan->lookupNode(curAddress); - listEntry = _listData; - for (listNr = 0; listNr < listCount; listNr++) { - curObject = curNode->value; - listEntry->object = curObject; + for (listNr = 0; curNode != 0; listNr++) { + AnimateEntry listEntry; + const reg_t curObject = curNode->value; + listEntry.object = curObject; // Get data from current object - listEntry->givenOrderNo = listNr; - listEntry->viewId = readSelectorValue(_s->_segMan, curObject, SELECTOR(view)); - listEntry->loopNo = readSelectorValue(_s->_segMan, curObject, SELECTOR(loop)); - listEntry->celNo = readSelectorValue(_s->_segMan, curObject, SELECTOR(cel)); - listEntry->paletteNo = readSelectorValue(_s->_segMan, curObject, SELECTOR(palette)); - listEntry->x = readSelectorValue(_s->_segMan, curObject, SELECTOR(x)); - listEntry->y = readSelectorValue(_s->_segMan, curObject, SELECTOR(y)); - listEntry->z = readSelectorValue(_s->_segMan, curObject, SELECTOR(z)); - listEntry->priority = readSelectorValue(_s->_segMan, curObject, SELECTOR(priority)); - listEntry->signal = readSelectorValue(_s->_segMan, curObject, SELECTOR(signal)); + listEntry.givenOrderNo = listNr; + listEntry.viewId = readSelectorValue(_s->_segMan, curObject, SELECTOR(view)); + listEntry.loopNo = readSelectorValue(_s->_segMan, curObject, SELECTOR(loop)); + listEntry.celNo = readSelectorValue(_s->_segMan, curObject, SELECTOR(cel)); + listEntry.paletteNo = readSelectorValue(_s->_segMan, curObject, SELECTOR(palette)); + listEntry.x = readSelectorValue(_s->_segMan, curObject, SELECTOR(x)); + listEntry.y = readSelectorValue(_s->_segMan, curObject, SELECTOR(y)); + listEntry.z = readSelectorValue(_s->_segMan, curObject, SELECTOR(z)); + listEntry.priority = readSelectorValue(_s->_segMan, curObject, SELECTOR(priority)); + listEntry.signal = readSelectorValue(_s->_segMan, curObject, SELECTOR(signal)); if (getSciVersion() >= SCI_VERSION_1_1) { // Cel scaling - listEntry->scaleSignal = readSelectorValue(_s->_segMan, curObject, SELECTOR(scaleSignal)); - if (listEntry->scaleSignal & kScaleSignalDoScaling) { - listEntry->scaleX = readSelectorValue(_s->_segMan, curObject, SELECTOR(scaleX)); - listEntry->scaleY = readSelectorValue(_s->_segMan, curObject, SELECTOR(scaleY)); + listEntry.scaleSignal = readSelectorValue(_s->_segMan, curObject, SELECTOR(scaleSignal)); + if (listEntry.scaleSignal & kScaleSignalDoScaling) { + listEntry.scaleX = readSelectorValue(_s->_segMan, curObject, SELECTOR(scaleX)); + listEntry.scaleY = readSelectorValue(_s->_segMan, curObject, SELECTOR(scaleY)); } else { - listEntry->scaleX = 128; - listEntry->scaleY = 128; + listEntry.scaleX = 128; + listEntry.scaleY = 128; } - // TODO - // On scaleSignal bit 1 sierra sci does some stuff with global var 2, current Port - // and some other stuff and sets scaleX/Y accordingly. It seems this functionality is needed in at - // least sq5 right when starting the game before wilco exists the room. Currently we dont get scaling - // but sierra sci does scaling there. I dont fully understand the code yet, that's why i didnt implement - // anything. } else { - listEntry->scaleSignal = 0; - listEntry->scaleX = 128; - listEntry->scaleY = 128; + listEntry.scaleSignal = 0; + listEntry.scaleX = 128; + listEntry.scaleY = 128; } - // listEntry->celRect is filled in AnimateFill() - listEntry->showBitsFlag = false; + // listEntry.celRect is filled in AnimateFill() + listEntry.showBitsFlag = false; _list.push_back(listEntry); - listEntry++; curAddress = curNode->succ; curNode = _s->_segMan->lookupNode(curAddress); } @@ -211,47 +178,73 @@ void GfxAnimate::makeSortedList(List *list) { void GfxAnimate::fill(byte &old_picNotValid) { reg_t curObject; - AnimateEntry *listEntry; uint16 signal; GfxView *view = NULL; - AnimateList::iterator listIterator; - AnimateList::iterator listEnd = _list.end(); + AnimateList::iterator it; + const AnimateList::iterator end = _list.end(); - listIterator = _list.begin(); - while (listIterator != listEnd) { - listEntry = *listIterator; - curObject = listEntry->object; + for (it = _list.begin(); it != end; ++it) { + curObject = it->object; // Get the corresponding view - view = _cache->getView(listEntry->viewId); + view = _cache->getView(it->viewId); // adjust loop and cel, if any of those is invalid - if (listEntry->loopNo >= view->getLoopCount()) { - listEntry->loopNo = 0; - writeSelectorValue(_s->_segMan, curObject, SELECTOR(loop), listEntry->loopNo); + if (it->loopNo >= view->getLoopCount()) { + it->loopNo = 0; + writeSelectorValue(_s->_segMan, curObject, SELECTOR(loop), it->loopNo); } - if (listEntry->celNo >= view->getCelCount(listEntry->loopNo)) { - listEntry->celNo = 0; - writeSelectorValue(_s->_segMan, curObject, SELECTOR(cel), listEntry->celNo); + if (it->celNo >= view->getCelCount(it->loopNo)) { + it->celNo = 0; + writeSelectorValue(_s->_segMan, curObject, SELECTOR(cel), it->celNo); + } + + // Process global scaling, if needed + if (it->scaleSignal & kScaleSignalDoScaling) { + if (it->scaleSignal & kScaleSignalGlobalScaling) { + // Global scaling uses global var 2 and some other stuff to calculate scaleX/scaleY + int16 maxScale = readSelectorValue(_s->_segMan, curObject, SELECTOR(maxScale)); + int16 celHeight = view->getHeight(it->loopNo, it->celNo); + int16 maxCelHeight = (maxScale * celHeight) >> 7; + reg_t globalVar2 = _s->variables[VAR_GLOBAL][2]; // current room object + int16 vanishingY = readSelectorValue(_s->_segMan, globalVar2, SELECTOR(vanishingY)); + + int16 fixedPortY = _ports->getPort()->rect.bottom - vanishingY; + int16 fixedEntryY = it->y - vanishingY; + if (!fixedEntryY) + fixedEntryY = 1; + + if ((celHeight == 0) || (fixedPortY == 0)) + error("global scaling panic"); + + it->scaleY = ( maxCelHeight * fixedEntryY ) / fixedPortY; + it->scaleY = (it->scaleY * 128) / celHeight; + + it->scaleX = it->scaleY; + + // and set objects scale selectors + writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleX), it->scaleX); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleY), it->scaleY); + } } // Create rect according to coordinates and given cel - if (listEntry->scaleSignal & kScaleSignalDoScaling) { - view->getCelScaledRect(listEntry->loopNo, listEntry->celNo, listEntry->x, listEntry->y, listEntry->z, listEntry->scaleX, listEntry->scaleY, &listEntry->celRect); + if (it->scaleSignal & kScaleSignalDoScaling) { + view->getCelScaledRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->scaleX, it->scaleY, it->celRect); } else { - view->getCelRect(listEntry->loopNo, listEntry->celNo, listEntry->x, listEntry->y, listEntry->z, &listEntry->celRect); + view->getCelRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->celRect); } - writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsLeft), listEntry->celRect.left); - writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsTop), listEntry->celRect.top); - writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsRight), listEntry->celRect.right); - writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsBottom), listEntry->celRect.bottom); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsLeft), it->celRect.left); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsTop), it->celRect.top); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsRight), it->celRect.right); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsBottom), it->celRect.bottom); - signal = listEntry->signal; + signal = it->signal; // Calculate current priority according to y-coordinate if (!(signal & kSignalFixedPriority)) { - listEntry->priority = _ports->kernelCoordinateToPriority(listEntry->y); - writeSelectorValue(_s->_segMan, curObject, SELECTOR(priority), listEntry->priority); + it->priority = _ports->kernelCoordinateToPriority(it->y); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(priority), it->priority); } if (signal & kSignalNoUpdate) { @@ -260,177 +253,154 @@ void GfxAnimate::fill(byte &old_picNotValid) { || (!(signal & kSignalHidden) && signal & kSignalRemoveView) || (signal & kSignalAlwaysUpdate)) old_picNotValid++; - signal &= 0xFFFF ^ kSignalStopUpdate; + signal &= ~kSignalStopUpdate; } else { if (signal & kSignalStopUpdate || signal & kSignalAlwaysUpdate) old_picNotValid++; - signal &= 0xFFFF ^ kSignalForceUpdate; + signal &= ~kSignalForceUpdate; } - listEntry->signal = signal; - - listIterator++; + it->signal = signal; } } void GfxAnimate::update() { reg_t curObject; - AnimateEntry *listEntry; uint16 signal; reg_t bitsHandle; Common::Rect rect; - AnimateList::iterator listIterator; - AnimateList::iterator listBegin = _list.begin(); - AnimateList::iterator listEnd = _list.end(); + AnimateList::iterator it; + const AnimateList::iterator end = _list.end(); // Remove all no-update cels, if requested - listIterator = _list.reverse_begin(); - while (listIterator != listEnd) { - listEntry = *listIterator; - curObject = listEntry->object; - signal = listEntry->signal; + for (it = _list.reverse_begin(); it != end; --it) { + curObject = it->object; + signal = it->signal; if (signal & kSignalNoUpdate) { if (!(signal & kSignalRemoveView)) { bitsHandle = readSelector(_s->_segMan, curObject, SELECTOR(underBits)); if (_screen->_picNotValid != 1) { _paint16->bitsRestore(bitsHandle); - listEntry->showBitsFlag = true; + it->showBitsFlag = true; } else { _paint16->bitsFree(bitsHandle); } writeSelectorValue(_s->_segMan, curObject, SELECTOR(underBits), 0); } - signal &= 0xFFFF ^ kSignalForceUpdate; - signal &= signal & kSignalViewUpdated ? 0xFFFF ^ (kSignalViewUpdated | kSignalNoUpdate) : 0xFFFF; + signal &= ~kSignalForceUpdate; + if (signal & kSignalViewUpdated) + signal &= ~(kSignalViewUpdated | kSignalNoUpdate); } else if (signal & kSignalStopUpdate) { - signal = (signal & (0xFFFF ^ kSignalStopUpdate)) | kSignalNoUpdate; + signal &= ~kSignalStopUpdate; + signal |= kSignalNoUpdate; } - listEntry->signal = signal; - listIterator--; + it->signal = signal; } // Draw always-update cels - listIterator = listBegin; - while (listIterator != listEnd) { - listEntry = *listIterator; - curObject = listEntry->object; - signal = listEntry->signal; + for (it = _list.begin(); it != end; ++it) { + curObject = it->object; + signal = it->signal; if (signal & kSignalAlwaysUpdate) { // draw corresponding cel - _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo, listEntry->scaleX, listEntry->scaleY); - listEntry->showBitsFlag = true; + _paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY); + it->showBitsFlag = true; - signal &= 0xFFFF ^ (kSignalStopUpdate | kSignalViewUpdated | kSignalNoUpdate | kSignalForceUpdate); + signal &= ~(kSignalStopUpdate | kSignalViewUpdated | kSignalNoUpdate | kSignalForceUpdate); if ((signal & kSignalIgnoreActor) == 0) { - rect = listEntry->celRect; - rect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(listEntry->priority) - 1, rect.top, rect.bottom - 1); + rect = it->celRect; + rect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(it->priority) - 1, rect.top, rect.bottom - 1); _paint16->fillRect(rect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15); } - listEntry->signal = signal; + it->signal = signal; } - listIterator++; } // Saving background for all NoUpdate-cels - listIterator = listBegin; - while (listIterator != listEnd) { - listEntry = *listIterator; - curObject = listEntry->object; - signal = listEntry->signal; + for (it = _list.begin(); it != end; ++it) { + curObject = it->object; + signal = it->signal; if (signal & kSignalNoUpdate) { if (signal & kSignalHidden) { signal |= kSignalRemoveView; } else { - signal &= 0xFFFF ^ kSignalRemoveView; + signal &= ~kSignalRemoveView; if (signal & kSignalIgnoreActor) - bitsHandle = _paint16->bitsSave(listEntry->celRect, GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY); + bitsHandle = _paint16->bitsSave(it->celRect, GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY); else - bitsHandle = _paint16->bitsSave(listEntry->celRect, GFX_SCREEN_MASK_ALL); + bitsHandle = _paint16->bitsSave(it->celRect, GFX_SCREEN_MASK_ALL); writeSelector(_s->_segMan, curObject, SELECTOR(underBits), bitsHandle); } - listEntry->signal = signal; + it->signal = signal; } - listIterator++; } // Draw NoUpdate cels - listIterator = listBegin; - while (listIterator != listEnd) { - listEntry = *listIterator; - curObject = listEntry->object; - signal = listEntry->signal; + for (it = _list.begin(); it != end; ++it) { + curObject = it->object; + signal = it->signal; if (signal & kSignalNoUpdate && !(signal & kSignalHidden)) { // draw corresponding cel - _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo, listEntry->scaleX, listEntry->scaleY); - listEntry->showBitsFlag = true; + _paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY); + it->showBitsFlag = true; - if ((signal & kSignalIgnoreActor) == 0) { - rect = listEntry->celRect; - rect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(listEntry->priority) - 1, rect.top, rect.bottom - 1); + if (!(signal & kSignalIgnoreActor)) { + rect = it->celRect; + rect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(it->priority) - 1, rect.top, rect.bottom - 1); _paint16->fillRect(rect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15); } } - listIterator++; } } void GfxAnimate::drawCels() { reg_t curObject; - AnimateEntry *listEntry; - AnimateEntry *lastCastEntry = _lastCastData; uint16 signal; reg_t bitsHandle; - AnimateList::iterator listIterator; - AnimateList::iterator listEnd = _list.end(); - _lastCastCount = 0; + AnimateList::iterator it; + const AnimateList::iterator end = _list.end(); + _lastCastData.clear(); - listIterator = _list.begin(); - while (listIterator != listEnd) { - listEntry = *listIterator; - curObject = listEntry->object; - signal = listEntry->signal; + for (it = _list.begin(); it != end; ++it) { + curObject = it->object; + signal = it->signal; if (!(signal & (kSignalNoUpdate | kSignalHidden | kSignalAlwaysUpdate))) { // Save background - bitsHandle = _paint16->bitsSave(listEntry->celRect, GFX_SCREEN_MASK_ALL); + bitsHandle = _paint16->bitsSave(it->celRect, GFX_SCREEN_MASK_ALL); writeSelector(_s->_segMan, curObject, SELECTOR(underBits), bitsHandle); // draw corresponding cel - _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo, listEntry->scaleX, listEntry->scaleY); - listEntry->showBitsFlag = true; + _paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY); + it->showBitsFlag = true; if (signal & kSignalRemoveView) { - signal &= 0xFFFF ^ kSignalRemoveView; + signal &= ~kSignalRemoveView; } - listEntry->signal = signal; + it->signal = signal; // Remember that entry in lastCast - memcpy(lastCastEntry, listEntry, sizeof(AnimateEntry)); - lastCastEntry++; _lastCastCount++; + _lastCastData.push_back(*it); } - listIterator++; } } void GfxAnimate::updateScreen(byte oldPicNotValid) { reg_t curObject; - AnimateEntry *listEntry; uint16 signal; - AnimateList::iterator listIterator; - AnimateList::iterator listEnd = _list.end(); + AnimateList::iterator it; + const AnimateList::iterator end = _list.end(); Common::Rect lsRect; Common::Rect workerRect; - listIterator = _list.begin(); - while (listIterator != listEnd) { - listEntry = *listIterator; - curObject = listEntry->object; - signal = listEntry->signal; + for (it = _list.begin(); it != end; ++it) { + curObject = it->object; + signal = it->signal; - if (listEntry->showBitsFlag || !(signal & (kSignalRemoveView | kSignalNoUpdate) || + if (it->showBitsFlag || !(signal & (kSignalRemoveView | kSignalNoUpdate) || (!(signal & kSignalRemoveView) && (signal & kSignalNoUpdate) && oldPicNotValid))) { lsRect.left = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsLeft)); lsRect.top = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsTop)); @@ -438,27 +408,27 @@ void GfxAnimate::updateScreen(byte oldPicNotValid) { lsRect.bottom = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsBottom)); workerRect = lsRect; - workerRect.clip(listEntry->celRect); + workerRect.clip(it->celRect); if (!workerRect.isEmpty()) { workerRect = lsRect; - workerRect.extend(listEntry->celRect); + workerRect.extend(it->celRect); } else { _paint16->bitsShow(lsRect); - workerRect = listEntry->celRect; + workerRect = it->celRect; } - writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsLeft), workerRect.left); - writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsTop), workerRect.top); - writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsRight), workerRect.right); - writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsBottom), workerRect.bottom); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsLeft), it->celRect.left); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsTop), it->celRect.top); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsRight), it->celRect.right); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsBottom), it->celRect.bottom); + // may get used for debugging + //_paint16->frameRect(workerRect); _paint16->bitsShow(workerRect); if (signal & kSignalHidden) { - listEntry->signal |= kSignalRemoveView; + it->signal |= kSignalRemoveView; } } - - listIterator++; } // use this for debug purposes // _screen->copyToScreen(); @@ -466,30 +436,26 @@ void GfxAnimate::updateScreen(byte oldPicNotValid) { void GfxAnimate::restoreAndDelete(int argc, reg_t *argv) { reg_t curObject; - AnimateEntry *listEntry; uint16 signal; - AnimateList::iterator listIterator; - AnimateList::iterator listEnd = _list.end(); + AnimateList::iterator it; + const AnimateList::iterator end = _list.end(); - // This has to be done in a separate loop. At least in sq1 some .dispose modifies FIXEDLOOP flag in signal for - // another object. In that case we would overwrite the new signal with our version of the old signal - listIterator = _list.begin(); - while (listIterator != listEnd) { - listEntry = *listIterator; - curObject = listEntry->object; - signal = listEntry->signal; + // This has to be done in a separate loop. At least in sq1 some .dispose + // modifies FIXEDLOOP flag in signal for another object. In that case we + // would overwrite the new signal with our version of the old signal. + for (it = _list.begin(); it != end; ++it) { + curObject = it->object; + signal = it->signal; // Finally update signal writeSelectorValue(_s->_segMan, curObject, SELECTOR(signal), signal); - listIterator++; } - listIterator = _list.reverse_begin(); - while (listIterator != listEnd) { - listEntry = *listIterator; - curObject = listEntry->object; - // We read out signal here again, this is not by accident but to ensure that we got an up-to-date signal + for (it = _list.reverse_begin(); it != end; --it) { + curObject = it->object; + // We read out signal here again, this is not by accident but to ensure + // that we got an up-to-date signal signal = readSelectorValue(_s->_segMan, curObject, SELECTOR(signal)); if ((signal & (kSignalNoUpdate | kSignalRemoveView)) == 0) { @@ -499,31 +465,24 @@ void GfxAnimate::restoreAndDelete(int argc, reg_t *argv) { if (signal & kSignalDisposeMe) { // Call .delete_ method of that object - invokeSelector(_s, curObject, g_sci->getKernel()->_selectorCache.delete_, kContinueOnInvalidSelector, argc, argv, 0); + invokeSelector(_s, curObject, SELECTOR(delete_), argc, argv, 0); } - listIterator--; } } void GfxAnimate::reAnimate(Common::Rect rect) { - AnimateEntry *lastCastEntry; - uint16 lastCastCount; - - if (_lastCastCount > 0) { - lastCastEntry = _lastCastData; - lastCastCount = _lastCastCount; - while (lastCastCount > 0) { - lastCastEntry->castHandle = _paint16->bitsSave(lastCastEntry->celRect, GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY); - _paint16->drawCel(lastCastEntry->viewId, lastCastEntry->loopNo, lastCastEntry->celNo, lastCastEntry->celRect, lastCastEntry->priority, lastCastEntry->paletteNo, lastCastEntry->scaleX, lastCastEntry->scaleY); - lastCastEntry++; lastCastCount--; + if (!_lastCastData.empty()) { + AnimateArray::iterator it; + AnimateArray::iterator end = _lastCastData.end(); + for (it = _lastCastData.begin(); it != end; ++it) { + it->castHandle = _paint16->bitsSave(it->celRect, GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY); + _paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY); } _paint16->bitsShow(rect); // restoring - lastCastCount = _lastCastCount; - while (lastCastCount > 0) { - lastCastEntry--; - _paint16->bitsRestore(lastCastEntry->castHandle); - lastCastCount--; + while (it != _lastCastData.begin()) { // FIXME: HACK, this iterator use is not very safe + it--; + _paint16->bitsRestore(it->castHandle); } } else { _paint16->bitsShow(rect); @@ -532,33 +491,28 @@ void GfxAnimate::reAnimate(Common::Rect rect) { void GfxAnimate::addToPicDrawCels() { reg_t curObject; - AnimateEntry *listEntry; GfxView *view = NULL; - AnimateList::iterator listIterator; - AnimateList::iterator listEnd = _list.end(); + AnimateList::iterator it; + const AnimateList::iterator end = _list.end(); - listIterator = _list.begin(); - while (listIterator != listEnd) { - listEntry = *listIterator; - curObject = listEntry->object; + for (it = _list.begin(); it != end; ++it) { + curObject = it->object; - if (listEntry->priority == -1) - listEntry->priority = _ports->kernelCoordinateToPriority(listEntry->y); + if (it->priority == -1) + it->priority = _ports->kernelCoordinateToPriority(it->y); // Get the corresponding view - view = _cache->getView(listEntry->viewId); + view = _cache->getView(it->viewId); // Create rect according to coordinates and given cel - view->getCelRect(listEntry->loopNo, listEntry->celNo, listEntry->x, listEntry->y, listEntry->z, &listEntry->celRect); + view->getCelRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->celRect); // draw corresponding cel - _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo); - if ((listEntry->signal & kSignalIgnoreActor) == 0) { - listEntry->celRect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(listEntry->priority) - 1, listEntry->celRect.top, listEntry->celRect.bottom - 1); - _paint16->fillRect(listEntry->celRect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15); + _paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo); + if ((it->signal & kSignalIgnoreActor) == 0) { + it->celRect.top = CLIP<int16>(_ports->kernelPriorityToCoordinate(it->priority) - 1, it->celRect.top, it->celRect.bottom - 1); + _paint16->fillRect(it->celRect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15); } - - listIterator++; } } @@ -567,7 +521,7 @@ void GfxAnimate::addToPicDrawView(GuiResourceId viewId, int16 loopNo, int16 celN Common::Rect celRect; // Create rect according to coordinates and given cel - view->getCelRect(loopNo, celNo, leftPos, topPos, priority, &celRect); + view->getCelRect(loopNo, celNo, leftPos, topPos, priority, celRect); _paint16->drawCel(view, loopNo, celNo, celRect, priority, 0); } @@ -592,6 +546,9 @@ void GfxAnimate::animateShowPic() { void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t *argv) { byte old_picNotValid = _screen->_picNotValid; + if (getSciVersion() >= SCI_VERSION_1_1) + _palette->palVaryUpdate(); + if (listReference.isNull()) { disposeLastCast(); if (_screen->_picNotValid) @@ -606,6 +563,9 @@ void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t if (cycle) { if (!invoke(list, argc, argv)) return; + + // Look up the list again, as it may have been modified + list = _s->_segMan->lookupList(listReference); } Port *oldPort = _ports->setPort((Port *)_ports->_picWind); @@ -615,9 +575,9 @@ void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t fill(old_picNotValid); if (old_picNotValid) { - // beginUpdate()/endUpdate() were introduced SCI1 - // calling those for SCI0 will work most of the time but breaks minor stuff like percentage bar of qfg1ega - // at the character skill screen + // beginUpdate()/endUpdate() were introduced SCI1. + // Calling those for SCI0 will work most of the time but breaks minor + // stuff like percentage bar of qfg1ega at the character skill screen. if (getSciVersion() >= SCI_VERSION_1_EGA) _ports->beginUpdate(_ports->_picWind); update(); @@ -633,7 +593,7 @@ void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t updateScreen(old_picNotValid); restoreAndDelete(argc, argv); - if (getLastCastCount() > 1) + if (_lastCastData.size() > 1) _s->_throttleTrigger = true; _ports->setPort(oldPort); diff --git a/engines/sci/graphics/animate.h b/engines/sci/graphics/animate.h index 706b7182cf..7e82187eed 100644 --- a/engines/sci/graphics/animate.h +++ b/engines/sci/graphics/animate.h @@ -51,9 +51,9 @@ enum ViewSignals { }; enum ViewScaleSignals { - kScaleSignalDoScaling = 0x0001, // enables scaling when drawing that cel (involves scaleX and scaleY) - kScaleSignalUnknown1 = 0x0002, // seems to do something with globalvar 2, sets scaleX/scaleY - kScaleSignalUnknown2 = 0x0004 // really unknown + kScaleSignalDoScaling = 0x0001, // enables scaling when drawing that cel (involves scaleX and scaleY) + kScaleSignalGlobalScaling = 0x0002, // means that global scaling shall get applied on that cel (sets scaleX/scaleY) + kScaleSignalUnknown2 = 0x0004 // really unknown }; struct AnimateEntry { @@ -73,7 +73,8 @@ struct AnimateEntry { bool showBitsFlag; reg_t castHandle; }; -typedef Common::List<AnimateEntry *> AnimateList; +typedef Common::List<AnimateEntry> AnimateList; +typedef Common::Array<AnimateEntry> AnimateArray; class GfxCache; class GfxCursor; @@ -90,9 +91,6 @@ public: GfxAnimate(EngineState *state, GfxCache *cache, GfxPorts *ports, GfxPaint16 *paint16, GfxScreen *screen, GfxPalette *palette, GfxCursor *cursor, GfxTransitions *transitions); virtual ~GfxAnimate(); - // FIXME: Don't store EngineState - void resetEngineState(EngineState *newState) { _s = newState; } - void disposeLastCast(); bool invoke(List *list, int argc, reg_t *argv); void makeSortedList(List *list); @@ -105,8 +103,6 @@ public: void addToPicDrawCels(); void addToPicDrawView(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 leftPos, int16 topPos, int16 priority, int16 control); - uint16 getLastCastCount() { return _lastCastCount; } - virtual void kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t *argv); virtual void kernelAddToPicList(reg_t listReference, int argc, reg_t *argv); virtual void kernelAddToPicView(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 leftPos, int16 topPos, int16 priority, int16 control); @@ -126,12 +122,8 @@ private: GfxCursor *_cursor; GfxTransitions *_transitions; - uint16 _listCount; - AnimateEntry *_listData; AnimateList _list; - - uint16 _lastCastCount; - AnimateEntry *_lastCastData; + AnimateArray _lastCastData; bool _ignoreFastCast; }; diff --git a/engines/sci/graphics/cache.cpp b/engines/sci/graphics/cache.cpp index 81bdab80ea..8caa28b3a1 100644 --- a/engines/sci/graphics/cache.cpp +++ b/engines/sci/graphics/cache.cpp @@ -102,7 +102,7 @@ int16 GfxCache::kernelViewGetLoopCount(GuiResourceId viewId) { } int16 GfxCache::kernelViewGetCelCount(GuiResourceId viewId, int16 loopNo) { - return getView(viewId)->getLoopInfo(loopNo)->celCount; + return getView(viewId)->getCelCount(loopNo); } } // End of namespace Sci diff --git a/engines/sci/graphics/cache.h b/engines/sci/graphics/cache.h index 16ab1916d4..2e9a345230 100644 --- a/engines/sci/graphics/cache.h +++ b/engines/sci/graphics/cache.h @@ -26,8 +26,6 @@ #ifndef SCI_GRAPHICS_CACHE_H #define SCI_GRAPHICS_CACHE_H -#include "sci/graphics/gui.h" - #include "common/hashmap.h" namespace Sci { diff --git a/engines/sci/graphics/compare.cpp b/engines/sci/graphics/compare.cpp index 3102edc2fa..31c2b210ce 100644 --- a/engines/sci/graphics/compare.cpp +++ b/engines/sci/graphics/compare.cpp @@ -28,6 +28,7 @@ #include "graphics/primitives.h" #include "sci/sci.h" +#include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/graphics/compare.h" @@ -126,14 +127,22 @@ void GfxCompare::kernelSetNowSeen(reg_t objectReference) { int16 x = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(x)); int16 y = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(y)); int16 z = 0; - if (_kernel->_selectorCache.z > -1) + if (SELECTOR(z) > -1) z = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(z)); - // now get cel rectangle view = _cache->getView(viewId); - view->getCelRect(loopNo, celNo, x, y, z, &celRect); - if (lookupSelector(_segMan, objectReference, _kernel->_selectorCache.nsTop, NULL, NULL) == kSelectorVariable) { + if (view->isSci2Hires()) + _screen->adjustToUpscaledCoordinates(y, x); + + view->getCelRect(loopNo, celNo, x, y, z, celRect); + + if (view->isSci2Hires()) { + _screen->adjustBackUpscaledCoordinates(celRect.top, celRect.left); + _screen->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right); + } + + if (lookupSelector(_segMan, objectReference, SELECTOR(nsTop), NULL, NULL) == kSelectorVariable) { writeSelectorValue(_segMan, objectReference, SELECTOR(nsLeft), celRect.left); writeSelectorValue(_segMan, objectReference, SELECTOR(nsRight), celRect.right); writeSelectorValue(_segMan, objectReference, SELECTOR(nsTop), celRect.top); @@ -174,19 +183,19 @@ bool GfxCompare::kernelCanBeHere(reg_t curObject, reg_t listReference) { bool GfxCompare::kernelIsItSkip(GuiResourceId viewId, int16 loopNo, int16 celNo, Common::Point position) { GfxView *tmpView = _cache->getView(viewId); - CelInfo *celInfo = tmpView->getCelInfo(loopNo, celNo); + const CelInfo *celInfo = tmpView->getCelInfo(loopNo, celNo); position.x = CLIP<int>(position.x, 0, celInfo->width - 1); position.y = CLIP<int>(position.y, 0, celInfo->height - 1); - byte *celData = tmpView->getBitmap(loopNo, celNo); + const byte *celData = tmpView->getBitmap(loopNo, celNo); bool result = (celData[position.y * celInfo->width + position.x] == celInfo->clearKey); return result; } void GfxCompare::kernelBaseSetter(reg_t object) { - if (lookupSelector(_segMan, object, _kernel->_selectorCache.brLeft, NULL, NULL) == kSelectorVariable) { + if (lookupSelector(_segMan, object, SELECTOR(brLeft), NULL, NULL) == kSelectorVariable) { int16 x = readSelectorValue(_segMan, object, SELECTOR(x)); int16 y = readSelectorValue(_segMan, object, SELECTOR(y)); - int16 z = (_kernel->_selectorCache.z > -1) ? readSelectorValue(_segMan, object, SELECTOR(z)) : 0; + int16 z = (SELECTOR(z) > -1) ? readSelectorValue(_segMan, object, SELECTOR(z)) : 0; int16 yStep = readSelectorValue(_segMan, object, SELECTOR(yStep)); GuiResourceId viewId = readSelectorValue(_segMan, object, SELECTOR(view)); int16 loopNo = readSelectorValue(_segMan, object, SELECTOR(loop)); @@ -199,7 +208,16 @@ void GfxCompare::kernelBaseSetter(reg_t object) { GfxView *tmpView = _cache->getView(viewId); Common::Rect celRect; - tmpView->getCelRect(loopNo, celNo, x, y, z, &celRect); + if (tmpView->isSci2Hires()) + _screen->adjustToUpscaledCoordinates(y, x); + + tmpView->getCelRect(loopNo, celNo, x, y, z, celRect); + + if (tmpView->isSci2Hires()) { + _screen->adjustBackUpscaledCoordinates(celRect.top, celRect.left); + _screen->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right); + } + celRect.bottom = y + 1; celRect.top = celRect.bottom - yStep; diff --git a/engines/sci/graphics/compare.h b/engines/sci/graphics/compare.h index 348d5ef723..be461cdc5b 100644 --- a/engines/sci/graphics/compare.h +++ b/engines/sci/graphics/compare.h @@ -26,8 +26,6 @@ #ifndef SCI_GRAPHICS_GFX_H #define SCI_GRAPHICS_GFX_H -#include "sci/graphics/gui.h" - #include "common/hashmap.h" namespace Sci { diff --git a/engines/sci/graphics/controls.cpp b/engines/sci/graphics/controls.cpp index 26af9741c2..ff5a91eed4 100644 --- a/engines/sci/graphics/controls.cpp +++ b/engines/sci/graphics/controls.cpp @@ -30,6 +30,7 @@ #include "sci/sci.h" #include "sci/event.h" +#include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/graphics/ports.h" diff --git a/engines/sci/graphics/coordadjuster.cpp b/engines/sci/graphics/coordadjuster.cpp index 422df52f27..9481a68f13 100644 --- a/engines/sci/graphics/coordadjuster.cpp +++ b/engines/sci/graphics/coordadjuster.cpp @@ -26,6 +26,7 @@ #include "common/util.h" #include "sci/sci.h" +#include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/graphics/coordadjuster.h" diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 2f8393f9ac..e1c05c97da 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -43,18 +43,18 @@ GfxCursor::GfxCursor(ResourceManager *resMan, GfxPalette *palette, GfxScreen *sc : _resMan(resMan), _palette(palette), _screen(screen) { _upscaledHires = _screen->getUpscaledHires(); + _isVisible = true; + // center mouse cursor setPosition(Common::Point(_screen->getWidth() / 2, _screen->getHeight() / 2)); kernelSetMoveZone(Common::Rect(0, 0, _screen->getDisplayWidth(), _screen->getDisplayHeight())); - - _isVisible = true; } GfxCursor::~GfxCursor() { purgeCache(); } -void GfxCursor::init(GfxCoordAdjuster *coordAdjuster, SciEvent *event) { +void GfxCursor::init(GfxCoordAdjuster *coordAdjuster, EventManager *event) { _coordAdjuster = coordAdjuster; _event = event; } @@ -120,7 +120,7 @@ void GfxCursor::kernelSetShape(GuiResourceId resourceId) { colorMapping[0] = 0; // Black is hardcoded colorMapping[1] = _screen->getColorWhite(); // White is also hardcoded colorMapping[2] = SCI_CURSOR_SCI0_TRANSPARENCYCOLOR; - colorMapping[3] = _palette->matchColor(&_palette->_sysPalette, 170, 170, 170); // Grey + colorMapping[3] = _palette->matchColor(170, 170, 170); // Grey // Seek to actual data resourceData += 4; @@ -164,42 +164,39 @@ void GfxCursor::kernelSetView(GuiResourceId viewNum, int loopNum, int celNum, Co GfxView *cursorView = _cachedCursors[viewNum]; - CelInfo *celInfo = cursorView->getCelInfo(loopNum, celNum); + const CelInfo *celInfo = cursorView->getCelInfo(loopNum, celNum); int16 width = celInfo->width; int16 height = celInfo->height; byte clearKey = celInfo->clearKey; Common::Point *cursorHotspot = hotspot; - byte *cursorBitmap; if (!cursorHotspot) // Compute hotspot from xoffset/yoffset cursorHotspot = new Common::Point((celInfo->width >> 1) - celInfo->displaceX, celInfo->height - celInfo->displaceY - 1); - // Eco Quest 1 uses a 1x1 transparent cursor to hide the cursor from the user. Some scalers don't seem to support this + // Eco Quest 1 uses a 1x1 transparent cursor to hide the cursor from the + // user. Some scalers don't seem to support this if (width < 2 || height < 2) { kernelHide(); delete cursorHotspot; return; } - celInfo->rawBitmap = cursorView->getBitmap(loopNum, celNum); + const byte *rawBitmap = cursorView->getBitmap(loopNum, celNum); if (_upscaledHires) { // Scale cursor by 2x - note: sierra didn't do this, but it looks much better width *= 2; height *= 2; cursorHotspot->x *= 2; cursorHotspot->y *= 2; - cursorBitmap = new byte[width * height]; - _screen->scale2x(celInfo->rawBitmap, cursorBitmap, celInfo->width, celInfo->height); + byte *cursorBitmap = new byte[width * height]; + _screen->scale2x(rawBitmap, cursorBitmap, celInfo->width, celInfo->height); + CursorMan.replaceCursor(cursorBitmap, width, height, cursorHotspot->x, cursorHotspot->y, clearKey); + delete[] cursorBitmap; } else { - cursorBitmap = celInfo->rawBitmap; + CursorMan.replaceCursor(rawBitmap, width, height, cursorHotspot->x, cursorHotspot->y, clearKey); } - CursorMan.replaceCursor(cursorBitmap, width, height, cursorHotspot->x, cursorHotspot->y, clearKey); - - if (_upscaledHires) - delete[] cursorBitmap; - kernelShow(); delete cursorHotspot; @@ -209,7 +206,7 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu // See http://developer.apple.com/legacy/mac/library/documentation/mac/QuickDraw/QuickDraw-402.html // for more information. - // View 998 seems to be a fake resource used to call for for the Mac CURS resources + // View 998 seems to be a fake resource used to call for the Mac CURS resources. // For other resources, they're still in the views, so use them. if (viewNum != 998) { kernelSetView(viewNum, loopNum, celNum, hotspot); @@ -219,6 +216,7 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu // TODO: What about the 2000 resources? Inventory items? How to handle? // TODO: What games does this work for? At least it does for KQ6. // TODO: Stop asking rhetorical questions. + // TODO: It was fred all along! Resource *resource = _resMan->findResource(ResourceId(kResourceTypeCursor, 1000 + celNum), false); @@ -258,6 +256,15 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu } void GfxCursor::setPosition(Common::Point pos) { + // Don't set position, when cursor is not visible. + // This fixes eco quest 1 (floppy) right at the start, which is setting + // mouse cursor to (0,0) all the time during the intro. It's escapeable + // (now) by moving to the left or top, but it's getting on your nerves. This + // could theoretically break some things, although sierra normally sets + // position only when showing the cursor. + if (!_isVisible) + return; + if (!_upscaledHires) { g_system->warpMouse(pos.x, pos.y); } else { @@ -269,21 +276,8 @@ void GfxCursor::setPosition(Common::Point pos) { Common::Point GfxCursor::getPosition() { Common::Point mousePos = g_system->getEventManager()->getMousePos(); - switch (_upscaledHires) { - case GFX_SCREEN_UPSCALED_640x400: - mousePos.x /= 2; - mousePos.y /= 2; - break; - case GFX_SCREEN_UPSCALED_640x440: - mousePos.x /= 2; - mousePos.y = (mousePos.y * 5) / 11; - break; - case GFX_SCREEN_UPSCALED_640x480: - mousePos.x /= 2; - mousePos.y = (mousePos.y * 5) / 12; - default: - break; - } + if (_upscaledHires) + _screen->adjustBackUpscaledCoordinates(mousePos.y, mousePos.x); return mousePos; } @@ -333,7 +327,7 @@ void GfxCursor::kernelMoveCursor(Common::Point pos) { // Trigger event reading to make sure the mouse coordinates will // actually have changed the next time we read them. - _event->get(SCI_EVENT_PEEK); + _event->getSciEvent(SCI_EVENT_PEEK); } } // End of namespace Sci diff --git a/engines/sci/graphics/cursor.h b/engines/sci/graphics/cursor.h index 6d92b3cf5f..7acd14acd9 100644 --- a/engines/sci/graphics/cursor.h +++ b/engines/sci/graphics/cursor.h @@ -45,7 +45,7 @@ public: GfxCursor(ResourceManager *resMan, GfxPalette *palette, GfxScreen *screen); ~GfxCursor(); - void init(GfxCoordAdjuster *coordAdjuster, SciEvent *event); + void init(GfxCoordAdjuster *coordAdjuster, EventManager *event); void kernelShow(); void kernelHide(); @@ -74,7 +74,7 @@ private: GfxScreen *_screen; GfxPalette *_palette; GfxCoordAdjuster *_coordAdjuster; - SciEvent *_event; + EventManager *_event; int _upscaledHires; diff --git a/engines/sci/graphics/font.cpp b/engines/sci/graphics/font.cpp index 91cf01c912..852771d081 100644 --- a/engines/sci/graphics/font.cpp +++ b/engines/sci/graphics/font.cpp @@ -82,17 +82,18 @@ void GfxFontFromResource::draw(uint16 chr, int16 top, int16 left, byte color, bo int charWidth = MIN<int>(getCharWidth(chr), _screen->getWidth() - left); int charHeight = MIN<int>(getCharHeight(chr), _screen->getHeight() - top); byte b = 0, mask = 0xFF; - int y = top; + int y = 0; + int16 greyedTop = top; byte *pIn = getCharData(chr); for (int i = 0; i < charHeight; i++, y++) { if (greyedOutput) - mask = top++ % 2 ? 0xAA : 0x55; + mask = greyedTop++ % 2 ? 0xAA : 0x55; for (int done = 0; done < charWidth; done++) { if ((done & 7) == 0) // fetching next data byte b = *(pIn++) & mask; if (b & 0x80) // if MSB is set - paint it - _screen->putPixel(left + done, y, 1, color, 0, 0); + _screen->putFontPixel(top, left + done, y, color); b = b << 1; } } diff --git a/engines/sci/graphics/fontsjis.h b/engines/sci/graphics/fontsjis.h index 24c8423ddb..684e6cac5e 100644 --- a/engines/sci/graphics/fontsjis.h +++ b/engines/sci/graphics/fontsjis.h @@ -26,10 +26,12 @@ #ifndef SCI_GRAPHICS_FONTSJIS_H #define SCI_GRAPHICS_FONTSJIS_H -#include "graphics/sjis.h" - #include "sci/graphics/helpers.h" +namespace Graphics { + class FontSJIS; +} + namespace Sci { /** diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 3cc5ca5447..9ce4474ee3 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -28,6 +28,7 @@ #include "graphics/primitives.h" #include "sci/sci.h" +#include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/engine/vm.h" @@ -37,6 +38,7 @@ #include "sci/graphics/view.h" #include "sci/graphics/screen.h" #include "sci/graphics/paint32.h" +#include "sci/graphics/palette.h" #include "sci/graphics/picture.h" #include "sci/graphics/frameout.h" @@ -46,7 +48,6 @@ GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAd : _segMan(segMan), _resMan(resMan), _cache(cache), _screen(screen), _palette(palette), _paint32(paint32) { _coordAdjuster = (GfxCoordAdjuster32 *)coordAdjuster; - _highPlanePri = 0; } GfxFrameout::~GfxFrameout() { @@ -54,30 +55,20 @@ GfxFrameout::~GfxFrameout() { void GfxFrameout::kernelAddPlane(reg_t object) { _planes.push_back(object); - int16 planePri = readSelectorValue(_segMan, object, SELECTOR(priority)) & 0xFFFF; - if (planePri > _highPlanePri) - _highPlanePri = planePri; + sortPlanes(); } void GfxFrameout::kernelUpdatePlane(reg_t object) { + sortPlanes(); } void GfxFrameout::kernelDeletePlane(reg_t object) { - for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) { - if (_planes[planeNr] == object) { - _planes.remove_at(planeNr); - break; + for (Common::List<reg_t>::iterator it = _planes.begin(); it != _planes.end(); it++) { + if (object == *it) { + _planes.erase(it); + return; } } - - // Recalculate highPlanePri - _highPlanePri = 0; - - for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) { - int16 planePri = readSelectorValue(_segMan, _planes[planeNr], SELECTOR(priority)) & 0xFFFF; - if (planePri > _highPlanePri) - _highPlanePri = planePri; - } } void GfxFrameout::kernelAddScreenItem(reg_t object) { @@ -95,73 +86,102 @@ void GfxFrameout::kernelDeleteScreenItem(reg_t object) { } int16 GfxFrameout::kernelGetHighPlanePri() { - return _highPlanePri; + sortPlanes(); + return readSelectorValue(g_sci->getEngineState()->_segMan, _planes.back(), SELECTOR(priority)); } bool sortHelper(const FrameoutEntry* entry1, const FrameoutEntry* entry2) { return (entry1->priority == entry2->priority) ? (entry1->y < entry2->y) : (entry1->priority < entry2->priority); } +bool planeSortHelper(const reg_t entry1, const reg_t entry2) { + SegManager *segMan = g_sci->getEngineState()->_segMan; + + uint16 plane1Priority = readSelectorValue(segMan, entry1, SELECTOR(priority)); + uint16 plane2Priority = readSelectorValue(segMan, entry2, SELECTOR(priority)); + + if (plane1Priority == 0xffff) + return true; + + if (plane2Priority == 0xffff) + return false; + + return plane1Priority < plane2Priority; +} + +void GfxFrameout::sortPlanes() { + // First, remove any invalid planes + for (Common::List<reg_t>::iterator it = _planes.begin(); it != _planes.end();) { + if (!_segMan->isObject(*it)) + it = _planes.erase(it); + else + it++; + } + + // Sort the rest of them + Common::sort(_planes.begin(), _planes.end(), planeSortHelper); +} + void GfxFrameout::kernelFrameout() { - int16 itemCount = 0; - reg_t planeObject; - GuiResourceId planePictureNr; - GfxPicture *planePicture = 0; - int16 planePictureCels = 0; - int16 planePictureCel; - int16 planePriority; - Common::Rect planeRect; - int16 planeResY, planeResX; - byte planeBack; - - reg_t itemObject; - reg_t itemPlane; - - FrameoutEntry *itemData; - FrameoutList itemList; - FrameoutEntry *itemEntry; + _palette->palVaryUpdate(); // Allocate enough space for all screen items - itemData = (FrameoutEntry *)malloc(_screenItems.size() * sizeof(FrameoutEntry)); + FrameoutEntry *itemData = (FrameoutEntry *)malloc(_screenItems.size() * sizeof(FrameoutEntry)); + + const SciGameId gameId = g_sci->getGameId(); - for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) { - planeObject = _planes[planeNr]; - planePriority = readSelectorValue(_segMan, planeObject, SELECTOR(priority)); + for (Common::List<reg_t>::iterator it = _planes.begin(); it != _planes.end(); it++) { + reg_t planeObject = *it; + uint16 planePriority = readSelectorValue(_segMan, planeObject, SELECTOR(priority)); - if (planePriority == -1) // Plane currently not meant to be shown + if (planePriority == 0xffff) // Plane currently not meant to be shown continue; + Common::Rect planeRect; planeRect.top = readSelectorValue(_segMan, planeObject, SELECTOR(top)); planeRect.left = readSelectorValue(_segMan, planeObject, SELECTOR(left)); planeRect.bottom = readSelectorValue(_segMan, planeObject, SELECTOR(bottom)); planeRect.right = readSelectorValue(_segMan, planeObject, SELECTOR(right)); - planeResY = readSelectorValue(_segMan, planeObject, SELECTOR(resY)); - planeResX = readSelectorValue(_segMan, planeObject, SELECTOR(resX)); + int16 planeResY = readSelectorValue(_segMan, planeObject, SELECTOR(resY)); + int16 planeResX = readSelectorValue(_segMan, planeObject, SELECTOR(resX)); planeRect.top = (planeRect.top * _screen->getHeight()) / planeResY; planeRect.left = (planeRect.left * _screen->getWidth()) / planeResX; planeRect.bottom = (planeRect.bottom * _screen->getHeight()) / planeResY; planeRect.right = (planeRect.right * _screen->getWidth()) / planeResX; - planeBack = readSelectorValue(_segMan, planeObject, SELECTOR(back)); - if (planeBack) { + byte planeBack = readSelectorValue(_segMan, planeObject, SELECTOR(back)); + if (planeBack) _paint32->fillRect(planeRect, planeBack); - } - planePictureNr = readSelectorValue(_segMan, planeObject, SELECTOR(picture)); + GuiResourceId planePictureNr = readSelectorValue(_segMan, planeObject, SELECTOR(picture)); + GfxPicture *planePicture = 0; + int16 planePictureCels = 0; + if ((planePictureNr != 0xFFFF) && (planePictureNr != 0xFFFE)) { planePicture = new GfxPicture(_resMan, _coordAdjuster, 0, _screen, _palette, planePictureNr, false); planePictureCels = planePicture->getSci32celCount(); _coordAdjuster->pictureSetDisplayArea(planeRect); + _palette->drewPicture(planePictureNr); } // Fill our itemlist for this plane - itemCount = 0; - itemEntry = itemData; + int16 itemCount = 0; + FrameoutEntry *itemEntry = itemData; + FrameoutList itemList; + for (uint32 itemNr = 0; itemNr < _screenItems.size(); itemNr++) { - itemObject = _screenItems[itemNr]; - itemPlane = readSelector(_segMan, itemObject, SELECTOR(plane)); + reg_t itemObject = _screenItems[itemNr]; + + // Remove any invalid items + if (!_segMan->isObject(itemObject)) { + _screenItems.remove_at(itemNr); + itemNr--; + continue; + } + + reg_t itemPlane = readSelector(_segMan, itemObject, SELECTOR(plane)); if (planeObject == itemPlane) { // Found an item on current plane itemEntry->viewId = readSelectorValue(_segMan, itemObject, SELECTOR(view)); @@ -171,6 +191,14 @@ void GfxFrameout::kernelFrameout() { itemEntry->y = readSelectorValue(_segMan, itemObject, SELECTOR(y)); itemEntry->z = readSelectorValue(_segMan, itemObject, SELECTOR(z)); itemEntry->priority = readSelectorValue(_segMan, itemObject, SELECTOR(priority)); + if (gameId == GID_GK1) { + if ((itemEntry->viewId == 11000) && (itemEntry->loopNo == 0) && (itemEntry->celNo == 0) && (itemEntry->priority == 1)) { + itemEntry->priority = 0; // HACK for gk1 hires main menu + } + if ((itemEntry->viewId == 10100) && (itemEntry->priority == 0)) { + itemEntry->priority = 1; // HACK for gk1 hires main menu + } + } itemEntry->signal = readSelectorValue(_segMan, itemObject, SELECTOR(signal)); itemEntry->scaleX = readSelectorValue(_segMan, itemObject, SELECTOR(scaleX)); itemEntry->scaleY = readSelectorValue(_segMan, itemObject, SELECTOR(scaleY)); @@ -181,8 +209,9 @@ void GfxFrameout::kernelFrameout() { itemEntry->y += planeRect.top; itemEntry->x += planeRect.left; - if (itemEntry->priority == 0) - itemEntry->priority = itemEntry->y; + if (!(itemEntry->signal & 0x0010)) { // kSignalFixedPriority + // TODO: Change priority of this item + } itemList.push_back(itemEntry); itemEntry++; @@ -194,12 +223,10 @@ void GfxFrameout::kernelFrameout() { Common::sort(itemList.begin(), itemList.end(), sortHelper); // Now display itemlist - planePictureCel = 0; - + int16 planePictureCel = 0; itemEntry = itemData; - FrameoutList::iterator listIterator = itemList.begin(); - FrameoutList::iterator listEnd = itemList.end(); - while (listIterator != listEnd) { + + for (FrameoutList::iterator listIterator = itemList.begin(); listIterator != itemList.end(); listIterator++) { itemEntry = *listIterator; if (planePicture) { while ((planePictureCel <= itemEntry->priority) && (planePictureCel < planePictureCels)) { @@ -207,63 +234,72 @@ void GfxFrameout::kernelFrameout() { planePictureCel++; } } + if (itemEntry->viewId != 0xFFFF) { GfxView *view = _cache->getView(itemEntry->viewId); - if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) { - view->getCelRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, &itemEntry->celRect); - } else - view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX, itemEntry->scaleY, &itemEntry->celRect); + if (view->isSci2Hires()) + _screen->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x); - if (itemEntry->celRect.top < 0 || itemEntry->celRect.top >= _screen->getHeight()) { - listIterator++; - continue; + if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) + view->getCelRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->celRect); + else + view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX, itemEntry->scaleY, itemEntry->celRect); + + int16 screenHeight = _screen->getHeight(); + int16 screenWidth = _screen->getWidth(); + if (view->isSci2Hires()) { + screenHeight = _screen->getDisplayHeight(); + screenWidth = _screen->getDisplayWidth(); } - if (itemEntry->celRect.left < 0 || itemEntry->celRect.left >= _screen->getWidth()) { - listIterator++; + if (itemEntry->celRect.top < 0 || itemEntry->celRect.top >= screenHeight) + continue; + + if (itemEntry->celRect.left < 0 || itemEntry->celRect.left >= screenWidth) continue; - } Common::Rect clipRect; clipRect = itemEntry->celRect; - clipRect.clip(planeRect); + if (view->isSci2Hires()) { + Common::Rect upscaledPlaneRect = planeRect; + _screen->adjustToUpscaledCoordinates(upscaledPlaneRect.top, upscaledPlaneRect.left); + _screen->adjustToUpscaledCoordinates(upscaledPlaneRect.bottom, upscaledPlaneRect.right); + clipRect.clip(upscaledPlaneRect); + } else { + clipRect.clip(planeRect); + } if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) - view->draw(itemEntry->celRect, clipRect, clipRect, itemEntry->loopNo, itemEntry->celNo, 255, 0, false); + view->draw(itemEntry->celRect, clipRect, clipRect, itemEntry->loopNo, itemEntry->celNo, 255, 0, view->isSci2Hires()); else view->drawScaled(itemEntry->celRect, clipRect, clipRect, itemEntry->loopNo, itemEntry->celNo, 255, itemEntry->scaleX, itemEntry->scaleY); } else { // Most likely a text entry // This draws text the "SCI0-SCI11" way. In SCI2, text is prerendered in kCreateTextBitmap // TODO: rewrite this the "SCI2" way (i.e. implement the text buffer to draw inside kCreateTextBitmap) - // This doesn't work for SCI2.1 games... - if (getSciVersion() == SCI_VERSION_2) { - Kernel *kernel = g_sci->getKernel(); - if (lookupSelector(_segMan, itemEntry->object, kernel->_selectorCache.text, NULL, NULL) == kSelectorVariable) { - Common::String text = _segMan->getString(readSelector(_segMan, itemEntry->object, SELECTOR(text))); - int16 fontRes = readSelectorValue(_segMan, itemEntry->object, SELECTOR(font)); - GfxFont *font = new GfxFontFromResource(_resMan, _screen, fontRes); - bool dimmed = readSelectorValue(_segMan, itemEntry->object, SELECTOR(dimmed)); - uint16 foreColor = readSelectorValue(_segMan, itemEntry->object, SELECTOR(fore)); - uint16 curX = itemEntry->x; - uint16 curY = itemEntry->y; - for (uint32 i = 0; i < text.size(); i++) { - // TODO: proper text splitting... this is a hack - if ((text[i] == ' ' && i > 0 && text[i - i] == ' ') || text[i] == '\n' || - (curX + font->getCharWidth(text[i]) > _screen->getWidth())) { - curY += font->getHeight(); - curX = itemEntry->x; - } - font->draw(text[i], curY, curX, foreColor, dimmed); - curX += font->getCharWidth(text[i]); + if (lookupSelector(_segMan, itemEntry->object, SELECTOR(text), NULL, NULL) == kSelectorVariable) { + Common::String text = _segMan->getString(readSelector(_segMan, itemEntry->object, SELECTOR(text))); + GfxFont *font = _cache->getFont(readSelectorValue(_segMan, itemEntry->object, SELECTOR(font))); + bool dimmed = readSelectorValue(_segMan, itemEntry->object, SELECTOR(dimmed)); + uint16 foreColor = readSelectorValue(_segMan, itemEntry->object, SELECTOR(fore)); + uint16 curX = itemEntry->x; + uint16 curY = itemEntry->y; + for (uint32 i = 0; i < text.size(); i++) { + unsigned char curChar = text[i]; + // TODO: proper text splitting... this is a hack + if ((curChar == ' ' && i > 0 && text[i - i] == ' ') || curChar == '\n' || + (curX + font->getCharWidth(curChar) > _screen->getWidth())) { + curY += font->getHeight(); + curX = itemEntry->x; } - delete font; + font->draw(curChar, curY, curX, foreColor, dimmed); + curX += font->getCharWidth(curChar); } } } - listIterator++; } + if (planePicture) { while (planePictureCel < planePictureCels) { planePicture->drawSci32Vga(planePictureCel); @@ -273,6 +309,7 @@ void GfxFrameout::kernelFrameout() { planePicture = 0; } } + free(itemData); _screen->copyToScreen(); } diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index 36c02af278..e4568ad602 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -41,10 +41,14 @@ struct FrameoutEntry { int16 scaleY; Common::Rect celRect; }; + typedef Common::List<FrameoutEntry *> FrameoutList; class GfxCache; +class GfxCoordAdjuster32; class GfxPaint32; +class GfxPalette; +class GfxScreen; /** * Frameout class, kFrameout and relevant functions for SCI32 games */ @@ -71,8 +75,9 @@ private: GfxPaint32 *_paint32; Common::Array<reg_t> _screenItems; - Common::Array<reg_t> _planes; - int16 _highPlanePri; + Common::List<reg_t> _planes; + + void sortPlanes(); }; } // End of namespace Sci diff --git a/engines/sci/graphics/gui.cpp b/engines/sci/graphics/gui.cpp deleted file mode 100644 index e427edd732..0000000000 --- a/engines/sci/graphics/gui.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/timer.h" -#include "common/util.h" - -#include "sci/sci.h" -#include "sci/debug.h" // for g_debug_sleeptime_factor -#include "sci/event.h" -#include "sci/engine/state.h" -#include "sci/engine/selector.h" -#include "sci/graphics/gui.h" -#include "sci/graphics/screen.h" -#include "sci/graphics/palette.h" -#include "sci/graphics/cursor.h" -#include "sci/graphics/ports.h" -#include "sci/graphics/paint16.h" -#include "sci/graphics/cache.h" -#include "sci/graphics/compare.h" -#include "sci/graphics/coordadjuster.h" -#include "sci/graphics/animate.h" -#include "sci/graphics/controls.h" -#include "sci/graphics/menu.h" -#include "sci/graphics/portrait.h" -#include "sci/graphics/text16.h" -#include "sci/graphics/transitions.h" -#include "sci/graphics/view.h" -#include "sci/sound/audio.h" - -namespace Sci { - -SciGui::SciGui(EngineState *state, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor, GfxPorts *ports, AudioPlayer *audio) - : _s(state), _screen(screen), _palette(palette), _cache(cache), _cursor(cursor), _ports(ports), _audio(audio) { - - // FIXME/TODO: If SciGui inits all the stuff below, then it should *own* it, - // not SciEngine. Conversely, if we want SciEngine to own this stuff, - // then it should init it! - _coordAdjuster = new GfxCoordAdjuster16(_ports); - g_sci->_gfxCoordAdjuster = _coordAdjuster; - _cursor->init(_coordAdjuster, _s->_event); - _compare = new GfxCompare(_s->_segMan, g_sci->getKernel(), _cache, _screen, _coordAdjuster); - g_sci->_gfxCompare = _compare; - _transitions = new GfxTransitions(this, _screen, _palette, g_sci->getResMan()->isVGA()); - _paint16 = new GfxPaint16(g_sci->getResMan(), _s->_segMan, g_sci->getKernel(), this, _cache, _ports, _coordAdjuster, _screen, _palette, _transitions); - g_sci->_gfxPaint = _paint16; - g_sci->_gfxPaint16 = _paint16; - _animate = new GfxAnimate(_s, _cache, _ports, _paint16, _screen, _palette, _cursor, _transitions); - g_sci->_gfxAnimate = _animate; - _text16 = new GfxText16(g_sci->getResMan(), _cache, _ports, _paint16, _screen); - _controls = new GfxControls(_s->_segMan, _ports, _paint16, _text16, _screen); - g_sci->_gfxControls = _controls; - _menu = new GfxMenu(_s->_event, _s->_segMan, this, _ports, _paint16, _text16, _screen, _cursor); - g_sci->_gfxMenu = _menu; -} - -SciGui::~SciGui() { - delete _menu; - delete _controls; - delete _text16; - delete _animate; - delete _paint16; - delete _transitions; - delete _compare; - delete _coordAdjuster; -} - -void SciGui::resetEngineState(EngineState *s) { - _s = s; - _animate->resetEngineState(s); -} - -void SciGui::init(bool usesOldGfxFunctions) { - _ports->init(usesOldGfxFunctions, this, _paint16, _text16); - _paint16->init(_animate, _text16); -} - -void SciGui::wait(int16 ticks) { - _s->wait(ticks); -} - -void SciGui::textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight) { - Common::Rect rect(0, 0, *textWidth, *textHeight); - _text16->Size(rect, text, font, maxWidth); - *textWidth = rect.width(); - *textHeight = rect.height(); -} - -// Used SCI1+ for text codes -void SciGui::textFonts(int argc, reg_t *argv) { - _text16->CodeSetFonts(argc, argv); -} - -// Used SCI1+ for text codes -void SciGui::textColors(int argc, reg_t *argv) { - _text16->CodeSetColors(argc, argv); -} - -reg_t SciGui::portraitLoad(Common::String resourceName) { - //Portrait *myPortrait = new Portrait(g_sci->getResMan(), _screen, _palette, resourceName); - return NULL_REG; -} - -void SciGui::portraitShow(Common::String resourceName, Common::Point position, uint16 resourceId, uint16 noun, uint16 verb, uint16 cond, uint16 seq) { - Portrait *myPortrait = new Portrait(g_sci->getResMan(), _s->_event, this, _screen, _palette, _audio, resourceName); - // TODO: cache portraits - // adjust given coordinates to curPort (but dont adjust coordinates on upscaledHires_Save_Box and give us hires coordinates - // on kDrawCel, yeah this whole stuff makes sense) - position.x += _ports->getPort()->left; position.y += _ports->getPort()->top; - _screen->adjustToUpscaledCoordinates(position.y, position.x); - myPortrait->doit(position, resourceId, noun, verb, cond, seq); - delete myPortrait; -} - -void SciGui::portraitUnload(uint16 portraitId) { -} - -} // End of namespace Sci diff --git a/engines/sci/graphics/gui.h b/engines/sci/graphics/gui.h deleted file mode 100644 index 7663036117..0000000000 --- a/engines/sci/graphics/gui.h +++ /dev/null @@ -1,91 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#ifndef SCI_GRAPHICS_GUI_H -#define SCI_GRAPHICS_GUI_H - -#include "sci/graphics/helpers.h" - -namespace Sci { - -class GfxScreen; -class GfxPalette; -class GfxCursor; -class GfxCache; -class GfxCompare; -class GfxCoordAdjuster16; -class GfxPorts; -class GfxPaint16; -class GfxAnimate; -class GfxControls; -class GfxMenu; -class GfxText16; -class GfxTransitions; - -class SciGui { -public: - SciGui(EngineState *s, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor, GfxPorts *ports, AudioPlayer *audio); - virtual ~SciGui(); - - virtual void init(bool usesOldGfxFunctions); - - virtual void wait(int16 ticks); - - virtual void textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight); - virtual void textFonts(int argc, reg_t *argv); - virtual void textColors(int argc, reg_t *argv); - - virtual reg_t portraitLoad(Common::String resourceName); - virtual void portraitShow(Common::String resourceName, Common::Point position, uint16 resourceNum, uint16 noun, uint16 verb, uint16 cond, uint16 seq); - virtual void portraitUnload(uint16 portraitId); - - // FIXME: Don't store EngineState - virtual void resetEngineState(EngineState *s); - -protected: - GfxCursor *_cursor; - EngineState *_s; - GfxScreen *_screen; - GfxPalette *_palette; - GfxCache *_cache; - GfxCoordAdjuster16 *_coordAdjuster; - GfxCompare *_compare; - GfxPorts *_ports; - GfxPaint16 *_paint16; - -private: - AudioPlayer *_audio; - GfxAnimate *_animate; - GfxControls *_controls; - GfxMenu *_menu; - GfxText16 *_text16; - GfxTransitions *_transitions; - - bool _usesOldGfxFunctions; -}; - -} // End of namespace Sci - -#endif diff --git a/engines/sci/graphics/gui32.cpp b/engines/sci/graphics/gui32.cpp deleted file mode 100644 index 4b72050d0b..0000000000 --- a/engines/sci/graphics/gui32.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/timer.h" -#include "common/util.h" - -#include "sci/sci.h" -#include "sci/event.h" -#include "sci/engine/state.h" -#include "sci/engine/selector.h" -#include "sci/graphics/gui32.h" -#include "sci/graphics/screen.h" -#include "sci/graphics/palette.h" -#include "sci/graphics/cursor.h" -#include "sci/graphics/cache.h" -#include "sci/graphics/compare.h" -#include "sci/graphics/coordadjuster.h" -#include "sci/graphics/frameout.h" -#include "sci/graphics/paint32.h" -#include "sci/graphics/picture.h" -#include "sci/graphics/robot.h" -#include "sci/graphics/view.h" - -namespace Sci { - -SciGui32::SciGui32(SegManager *segMan, SciEvent *event, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor) - : _screen(screen), _palette(palette), _cache(cache), _cursor(cursor) { - - _coordAdjuster = new GfxCoordAdjuster32(segMan); - g_sci->_gfxCoordAdjuster = _coordAdjuster; - _cursor->init(_coordAdjuster, event); - _compare = new GfxCompare(segMan, g_sci->getKernel(), _cache, _screen, _coordAdjuster); - g_sci->_gfxCompare = _compare; - _paint32 = new GfxPaint32(g_sci->getResMan(), segMan, g_sci->getKernel(), _coordAdjuster, _cache, _screen, _palette); - g_sci->_gfxPaint = _paint32; - _frameout = new GfxFrameout(segMan, g_sci->getResMan(), _coordAdjuster, _cache, _screen, _palette, _paint32); - g_sci->_gfxFrameout = _frameout; -} - -SciGui32::~SciGui32() { - delete _frameout; - delete _paint32; - delete _compare; - delete _coordAdjuster; -} - -void SciGui32::init() { -} - -void SciGui32::textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight) { - *textWidth = 0; - *textHeight = 0; -} - -void SciGui32::drawRobot(GuiResourceId robotId) { - Robot *test = new Robot(g_sci->getResMan(), _screen, robotId); - test->draw(); - delete test; -} - -} // End of namespace Sci diff --git a/engines/sci/graphics/maciconbar.cpp b/engines/sci/graphics/maciconbar.cpp index a06e98ccbf..6f2c9596db 100644 --- a/engines/sci/graphics/maciconbar.cpp +++ b/engines/sci/graphics/maciconbar.cpp @@ -24,6 +24,7 @@ */ #include "sci/sci.h" +#include "sci/engine/kernel.h" #include "sci/engine/selector.h" #include "sci/engine/state.h" #include "sci/graphics/maciconbar.h" diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp index 880e1aba12..bfe58e03d5 100644 --- a/engines/sci/graphics/menu.cpp +++ b/engines/sci/graphics/menu.cpp @@ -29,9 +29,9 @@ #include "sci/sci.h" #include "sci/event.h" +#include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" -#include "sci/graphics/gui.h" #include "sci/graphics/ports.h" #include "sci/graphics/paint16.h" #include "sci/graphics/animate.h" @@ -43,8 +43,8 @@ namespace Sci { -GfxMenu::GfxMenu(SciEvent *event, SegManager *segMan, SciGui *gui, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen, GfxCursor *cursor) - : _event(event), _segMan(segMan), _gui(gui), _ports(ports), _paint16(paint16), _text16(text16), _screen(screen), _cursor(cursor) { +GfxMenu::GfxMenu(EventManager *event, SegManager *segMan, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen, GfxCursor *cursor) + : _event(event), _segMan(segMan), _ports(ports), _paint16(paint16), _text16(text16), _screen(screen), _cursor(cursor) { _menuSaveHandle = NULL_REG; _barSaveHandle = NULL_REG; @@ -63,8 +63,9 @@ void GfxMenu::reset() { _itemList.clear(); _listCount = 0; - // We actually set active item in here and remember last selection of the user - // sierra sci always defaulted to first item every time menu was called via ESC, we dont follow that logic + // We actually set active item in here and remember last selection of the + // user. Sierra SCI always defaulted to first item every time menu was + // called via ESC, we don't follow that logic. _curMenuId = 1; _curItemId = 1; } @@ -92,15 +93,16 @@ void GfxMenu::kernelAddEntry(Common::String title, Common::String content, reg_t beginPos = curPos; - // Now go through the content till we find end-marker and collect data about it - // ':' is an end-marker for each item + // Now go through the content till we find end-marker and collect data about it. + // ':' is an end-marker for each item. tagPos = 0; rightAlignedPos = 0; controlPos = 0; altPos = 0; functionPos = 0; while ((curPos < contentSize) && (content[curPos] != ':')) { switch (content[curPos]) { case '=': // Set tag - // Special case for normal animation speed - they use right aligned "=" for that one, so we ignore it - // as being recognized as tag marker + // Special case for normal animation speed - they use right + // aligned "=" for that one, so we ignore it as being recognized + // as tag marker. if (rightAlignedPos == curPos - 1) break; if (tagPos) @@ -199,8 +201,9 @@ void GfxMenu::kernelAddEntry(Common::String title, Common::String content, reg_t if (separatorCount == tempPos - beginPos) { itemEntry->separatorLine = true; } else { - // we don't strSplit here, because multilingual SCI01 support language switching on the fly, so we have to do - // this everytime the menu is called + // We don't strSplit here, because multilingual SCI01 support + // language switching on the fly, so we have to do this everytime + // the menu is called. itemEntry->text = Common::String(content.c_str() + beginPos, tempPos - beginPos); // LSL6 uses "Ctrl-" prefix string instead of ^ like all the other games do @@ -222,10 +225,12 @@ void GfxMenu::kernelAddEntry(Common::String title, Common::String content, reg_t if (tagPos && tagPos >= rightAlignedPos) tempPos = tagPos; itemEntry->textRightAligned = Common::String(content.c_str() + rightAlignedPos, tempPos - rightAlignedPos); - // Remove ending space, if there is one. Strangely sometimes there are lone spaces at the end in some games + // Remove ending space, if there is one. Strangely sometimes there + // are lone spaces at the end in some games if (itemEntry->textRightAligned.hasSuffix(" ")) itemEntry->textRightAligned.deleteLastChar(); - // - and + are used sometimes for volume control/animation speed, = sometimes for animation speed + // - and + are used sometimes for volume control/animation speed, + // = sometimes for animation speed if (itemEntry->textRightAligned == "-") { itemEntry->keyPress = '-'; } else if (itemEntry->textRightAligned == "+") { @@ -377,7 +382,7 @@ void GfxMenu::calculateMenuAndItemWidth() { } } -reg_t GfxMenu::kernelSelect(reg_t eventObject) { +reg_t GfxMenu::kernelSelect(reg_t eventObject, bool pauseSound) { int16 eventType = readSelectorValue(_segMan, eventObject, SELECTOR(type)); int16 keyPress, keyModifier; Common::Point mousePosition; @@ -392,7 +397,8 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject) { case SCI_EVENT_KEYBOARD: keyPress = readSelectorValue(_segMan, eventObject, SELECTOR(message)); keyModifier = readSelectorValue(_segMan, eventObject, SELECTOR(modifiers)); - // If tab got pressed, handle it here as if it was Ctrl-I - at least sci0 also did it that way + // If tab got pressed, handle it here as if it was Ctrl-I - at least + // sci0 also did it that way if (keyPress == SCI_KEY_TAB) { keyModifier = SCI_KEYMOD_CTRL; keyPress = 'i'; @@ -401,9 +407,9 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject) { case 0: break; case SCI_KEY_ESC: - interactiveShowMouse(); + interactiveStart(pauseSound); itemEntry = interactiveWithKeyboard(); - interactiveRestoreMouse(); + interactiveEnd(pauseSound); forceClaimed = true; break; default: @@ -439,9 +445,9 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject) { case SCI_EVENT_MOUSE_PRESS: mousePosition = _cursor->getPosition(); if (mousePosition.y < 10) { - interactiveShowMouse(); + interactiveStart(pauseSound); itemEntry = interactiveWithMouse(); - interactiveRestoreMouse(); + interactiveEnd(pauseSound); forceClaimed = true; } break; @@ -562,7 +568,8 @@ void GfxMenu::drawMenu(uint16 oldMenuId, uint16 newMenuId) { if (!maxTextRightAlignedWidth) _menuRect.right -= 5; - // if part of menu window is outside the screen, move it into the screen (this happens in multilingual sq3 and lsl3) + // If part of menu window is outside the screen, move it into the screen + // (this happens in multilingual sq3 and lsl3). if (_menuRect.right > _screen->getWidth()) { _menuRect.translate(-(_menuRect.right - _screen->getWidth()), 0); } @@ -625,12 +632,16 @@ void GfxMenu::invertMenuSelection(uint16 itemId) { _paint16->bitsShow(itemRect); } -void GfxMenu::interactiveShowMouse() { +void GfxMenu::interactiveStart(bool pauseSound) { _mouseOldState = _cursor->isVisible(); _cursor->kernelShow(); + if (pauseSound) + g_sci->_soundCmd->pauseAll(true); } -void GfxMenu::interactiveRestoreMouse() { +void GfxMenu::interactiveEnd(bool pauseSound) { + if (pauseSound) + g_sci->_soundCmd->pauseAll(false); if (!_mouseOldState) _cursor->kernelHide(); } @@ -682,18 +693,19 @@ uint16 GfxMenu::mouseFindMenuItemSelection(Common::Point mousePosition, uint16 m } GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() { - sciEvent curEvent; + SciEvent curEvent; uint16 newMenuId = _curMenuId; uint16 newItemId = _curItemId; GuiMenuItemEntry *curItemEntry = findItem(_curMenuId, _curItemId); GuiMenuItemEntry *newItemEntry = curItemEntry; Common::Point mousePosition; - // We don't 100% follow sierra here: we select last item instead of selecting first item of first menu everytime - // Also sierra sci didnt allow mouse interaction, when menu was activated via keyboard + // We don't 100% follow Sierra here: we select last item instead of + // selecting first item of first menu every time. Also sierra sci didn't + // allow mouse interaction, when menu was activated via keyboard. - calculateMenuAndItemWidth(); _oldPort = _ports->setPort(_ports->_menuPort); + calculateMenuAndItemWidth(); _barSaveHandle = _paint16->bitsSave(_ports->_menuRect, GFX_SCREEN_MASK_VISUAL); _ports->penColor(0); @@ -706,12 +718,13 @@ GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() { _paint16->bitsShow(_menuRect); while (true) { - curEvent = _event->get(SCI_EVENT_ANY); + curEvent = _event->getSciEvent(SCI_EVENT_ANY); switch (curEvent.type) { case SCI_EVENT_KEYBOARD: - // We don't 100% follow sierra here: - sierra didn't wrap around when changing item id - // - sierra allowed item id to be 0, which didnt make any sense + // We don't 100% follow sierra here: + // - sierra didn't wrap around when changing item id + // - sierra allowed item id to be 0, which didn't make any sense do { switch (curEvent.data) { case SCI_KEY_ESC: @@ -796,25 +809,26 @@ GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() { } break; case SCI_EVENT_NONE: - _event->sleep(2500 / 1000); + g_sci->sleep(2500 / 1000); break; } } } -// Mouse button is currently pressed - we are now interpreting mouse coordinates till mouse button is released -// The menu item that is selected at that time is chosen. If no menu item is selected we cancel -// No keyboard interaction is allowed, cause that wouldnt make any sense at all +// Mouse button is currently pressed - we are now interpreting mouse coordinates +// till mouse button is released. The menu item that is selected at that time is +// chosen. If no menu item is selected we cancel. No keyboard interaction is +// allowed, cause that wouldnt make any sense at all. GuiMenuItemEntry *GfxMenu::interactiveWithMouse() { - sciEvent curEvent; + SciEvent curEvent; uint16 newMenuId = 0, newItemId = 0; uint16 curMenuId = 0, curItemId = 0; Common::Point mousePosition = _cursor->getPosition(); bool firstMenuChange = true; GuiMenuItemEntry *curItemEntry = NULL; - calculateMenuAndItemWidth(); _oldPort = _ports->setPort(_ports->_menuPort); + calculateMenuAndItemWidth(); _barSaveHandle = _paint16->bitsSave(_ports->_menuRect, GFX_SCREEN_MASK_VISUAL); _ports->penColor(0); @@ -824,7 +838,7 @@ GuiMenuItemEntry *GfxMenu::interactiveWithMouse() { _paint16->bitsShow(_ports->_menuRect); while (true) { - curEvent = _event->get(SCI_EVENT_ANY); + curEvent = _event->getSciEvent(SCI_EVENT_ANY); switch (curEvent.type) { case SCI_EVENT_MOUSE_RELEASE: @@ -835,7 +849,7 @@ GuiMenuItemEntry *GfxMenu::interactiveWithMouse() { return curItemEntry; case SCI_EVENT_NONE: - _event->sleep(2500 / 1000); + g_sci->sleep(2500 / 1000); break; } diff --git a/engines/sci/graphics/menu.h b/engines/sci/graphics/menu.h index 8f23b46ff8..9a14d4c64a 100644 --- a/engines/sci/graphics/menu.h +++ b/engines/sci/graphics/menu.h @@ -83,7 +83,7 @@ typedef Common::List<GuiMenuItemEntry *> GuiMenuItemList; */ class GfxMenu { public: - GfxMenu(SciEvent *event, SegManager *segMan, SciGui *gui, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen, GfxCursor *cursor); + GfxMenu(EventManager *event, SegManager *segMan, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen, GfxCursor *cursor); ~GfxMenu(); void reset(); @@ -92,7 +92,7 @@ public: reg_t kernelGetAttribute(uint16 menuId, uint16 itemId, uint16 attributeId); void drawBar(); - reg_t kernelSelect(reg_t eventObject); + reg_t kernelSelect(reg_t eventObject, bool pauseSound); void kernelDrawStatus(const char *text, int16 colorPen, int16 colorBack); void kernelDrawMenuBar(bool clear); @@ -103,17 +103,16 @@ private: void calculateMenuAndItemWidth(); void drawMenu(uint16 oldMenuId, uint16 newMenuId); void invertMenuSelection(uint16 itemId); - void interactiveShowMouse(); - void interactiveRestoreMouse(); + void interactiveStart(bool pauseSound); + void interactiveEnd(bool pauseSound); GuiMenuItemEntry *interactiveWithKeyboard(); GuiMenuItemEntry *interactiveWithMouse(); uint16 mouseFindMenuSelection(Common::Point mousePosition); uint16 mouseFindMenuItemSelection(Common::Point mousePosition, uint16 menuId); GuiMenuItemEntry *interactiveGetItem(uint16 menuId, uint16 itemId, bool menuChanged); - SciEvent *_event; + EventManager *_event; SegManager *_segMan; - SciGui *_gui; GfxPorts *_ports; GfxPaint16 *_paint16; GfxText16 *_text16; diff --git a/engines/sci/graphics/paint.h b/engines/sci/graphics/paint.h index f1342d55e5..75a17461d4 100644 --- a/engines/sci/graphics/paint.h +++ b/engines/sci/graphics/paint.h @@ -26,8 +26,6 @@ #ifndef SCI_GRAPHICS_PAINT_H #define SCI_GRAPHICS_PAINT_H -#include "sci/graphics/gui.h" - #include "common/hashmap.h" namespace Sci { diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index ff4f3bec52..90b05c68a6 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -42,13 +42,14 @@ #include "sci/graphics/view.h" #include "sci/graphics/screen.h" #include "sci/graphics/palette.h" +#include "sci/graphics/portrait.h" #include "sci/graphics/text16.h" #include "sci/graphics/transitions.h" namespace Sci { -GfxPaint16::GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, SciGui *gui, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions) - : _resMan(resMan), _segMan(segMan), _kernel(kernel), _gui(gui), _cache(cache), _ports(ports), _coordAdjuster(coordAdjuster), _screen(screen), _palette(palette), _transitions(transitions) { +GfxPaint16::GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions, AudioPlayer *audio) + : _resMan(resMan), _segMan(segMan), _kernel(kernel), _cache(cache), _ports(ports), _coordAdjuster(coordAdjuster), _screen(screen), _palette(palette), _transitions(transitions), _audio(audio) { } GfxPaint16::~GfxPaint16() { @@ -74,6 +75,11 @@ void GfxPaint16::drawPicture(GuiResourceId pictureId, int16 animationNr, bool mi picture->draw(animationNr, mirroredFlag, addToFlag, paletteId); delete picture; + + // We make a call to SciPalette here, for increasing sys timestamp and also loading targetpalette, if palvary active + // (SCI1.1 only) + if (getSciVersion() == SCI_VERSION_1_1) + _palette->drewPicture(pictureId); } // This one is the only one that updates screen! @@ -101,12 +107,12 @@ void GfxPaint16::drawCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, } // This version of drawCel is not supposed to call BitsShow()! -void GfxPaint16::drawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) { +void GfxPaint16::drawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, const Common::Rect &celRect, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) { drawCel(_cache->getView(viewId), loopNo, celNo, celRect, priority, paletteNo, scaleX, scaleY); } // This version of drawCel is not supposed to call BitsShow()! -void GfxPaint16::drawCel(GfxView *view, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) { +void GfxPaint16::drawCel(GfxView *view, int16 loopNo, int16 celNo, const Common::Rect &celRect, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) { Common::Rect clipRect = celRect; clipRect.clip(_ports->_curPort->rect); if (clipRect.isEmpty()) // nothing to draw @@ -121,8 +127,8 @@ void GfxPaint16::drawCel(GfxView *view, int16 loopNo, int16 celNo, Common::Rect } } -// This is used as replacement for drawCelAndShow() when hires-cels are drawn to screen -// Hires-cels are available only SCI 1.1+ +// This is used as replacement for drawCelAndShow() when hires-cels are drawn to +// screen. Hires-cels are available only SCI 1.1+. void GfxPaint16::drawHiresCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo, reg_t upscaledHiresHandle, uint16 scaleX, uint16 scaleY) { GfxView *view = _cache->getView(viewId); Common::Rect celRect, curPortRect, clipRect, clipRectTranslated; @@ -131,9 +137,10 @@ void GfxPaint16::drawHiresCelAndShow(GuiResourceId viewId, int16 loopNo, int16 c if (view) { if ((leftPos == 0) && (topPos == 0)) { - // HACK: in kq6, we get leftPos&topPos == 0 SOMETIMES, that's why we need to get coordinates from upscaledHiresHandle - // I'm not sure if this is what we are supposed to do or if there is some other bug that actually makes - // coordinates to be 0 in the first place + // HACK: in kq6, we get leftPos&topPos == 0 SOMETIMES, that's why we + // need to get coordinates from upscaledHiresHandle. I'm not sure if + // this is what we are supposed to do or if there is some other bug + // that actually makes coordinates to be 0 in the first place. byte *memoryPtr = NULL; memoryPtr = _segMan->getHunkPointer(upscaledHiresHandle); if (memoryPtr) { @@ -310,11 +317,12 @@ reg_t GfxPaint16::bitsSave(const Common::Rect &rect, byte screenMask) { return NULL_REG; if (screenMask == GFX_SCREEN_MASK_DISPLAY) { + // The coordinates we are given are actually up-to-including right/bottom - we extend accordingly + workerRect.bottom++; + workerRect.right++; // Adjust rect to upscaled hires, but dont adjust according to port _screen->adjustToUpscaledCoordinates(workerRect.top, workerRect.left); _screen->adjustToUpscaledCoordinates(workerRect.bottom, workerRect.right); - workerRect.bottom++; - workerRect.right++; } else { _ports->offsetRect(workerRect); } @@ -324,7 +332,8 @@ reg_t GfxPaint16::bitsSave(const Common::Rect &rect, byte screenMask) { memoryId = _segMan->allocateHunkEntry("SaveBits()", size); memoryPtr = _segMan->getHunkPointer(memoryId); - _screen->bitsSave(workerRect, screenMask, memoryPtr); + if (memoryPtr) + _screen->bitsSave(workerRect, screenMask, memoryPtr); return memoryId; } @@ -374,7 +383,8 @@ void GfxPaint16::kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, b } void GfxPaint16::kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle) { - // some calls are hiresMode even under kq6 DOS, that's why we check for upscaled hires here + // some calls are hiresMode even under kq6 DOS, that's why we check for + // upscaled hires here if ((!hiresMode) || (!_screen->getUpscaledHires())) { drawCelAndShow(viewId, loopNo, celNo, leftPos, topPos, priority, paletteNo); } else { @@ -382,19 +392,19 @@ void GfxPaint16::kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, } } -void GfxPaint16::kernelGraphFillBoxForeground(Common::Rect rect) { +void GfxPaint16::kernelGraphFillBoxForeground(const Common::Rect &rect) { paintRect(rect); } -void GfxPaint16::kernelGraphFillBoxBackground(Common::Rect rect) { +void GfxPaint16::kernelGraphFillBoxBackground(const Common::Rect &rect) { eraseRect(rect); } -void GfxPaint16::kernelGraphFillBox(Common::Rect rect, uint16 colorMask, int16 color, int16 priority, int16 control) { +void GfxPaint16::kernelGraphFillBox(const Common::Rect &rect, uint16 colorMask, int16 color, int16 priority, int16 control) { fillRect(rect, colorMask, color, priority, control); } -void GfxPaint16::kernelGraphFrameBox(Common::Rect rect, int16 color) { +void GfxPaint16::kernelGraphFrameBox(const Common::Rect &rect, int16 color) { int16 oldColor = _ports->getPort()->penClr; _ports->penColor(color); frameRect(rect); @@ -406,11 +416,11 @@ void GfxPaint16::kernelGraphDrawLine(Common::Point startPoint, Common::Point end _screen->drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y, color, priority, control); } -reg_t GfxPaint16::kernelGraphSaveBox(Common::Rect rect, uint16 screenMask) { +reg_t GfxPaint16::kernelGraphSaveBox(const Common::Rect &rect, uint16 screenMask) { return bitsSave(rect, screenMask); } -reg_t GfxPaint16::kernelGraphSaveUpscaledHiresBox(Common::Rect rect) { +reg_t GfxPaint16::kernelGraphSaveUpscaledHiresBox(const Common::Rect &rect) { return bitsSave(rect, GFX_SCREEN_MASK_DISPLAY); } @@ -418,8 +428,9 @@ void GfxPaint16::kernelGraphRestoreBox(reg_t handle) { bitsRestore(handle); } -void GfxPaint16::kernelGraphUpdateBox(Common::Rect rect, bool hiresMode) { - // some calls are hiresMode even under kq6 DOS, that's why we check for upscaled hires here +void GfxPaint16::kernelGraphUpdateBox(const Common::Rect &rect, bool hiresMode) { + // some calls are hiresMode even under kq6 DOS, that's why we check for + // upscaled hires here if ((!hiresMode) || (!_screen->getUpscaledHires())) bitsShow(rect); else @@ -447,6 +458,8 @@ void GfxPaint16::kernelGraphRedrawBox(Common::Rect rect) { #define SCI_DISPLAY_WIDTH 106 #define SCI_DISPLAY_SAVEUNDER 107 #define SCI_DISPLAY_RESTOREUNDER 108 +#define SCI_DISPLAY_DUMMY1 114 // used in longbow-demo, not supported in sierra sci - no parameters +#define SCI_DISPLAY_DUMMY2 115 // used in longbow-demo, not supported in sierra sci - has 1 parameter #define SCI_DISPLAY_DONTSHOWBITS 121 reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { @@ -457,7 +470,8 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { Common::Rect rect; reg_t result = NULL_REG; - // Make a "backup" of the port settings (required for some SCI0LATE and SCI01+ only) + // Make a "backup" of the port settings (required for some SCI0LATE and + // SCI01+ only) Port oldPort = *_ports->getPort(); // setting defaults @@ -512,8 +526,24 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { case SCI_DISPLAY_DONTSHOWBITS: bRedraw = 0; break; + + // 2 Dummy functions, longbow-demo is using those several times but sierra sci doesn't support them at all + case SCI_DISPLAY_DUMMY1: + case SCI_DISPLAY_DUMMY2: + if (!((g_sci->getGameId() == GID_LONGBOW) && (g_sci->isDemo()))) + error("Unknown kDisplay argument %X", displayArg); + if (displayArg == SCI_DISPLAY_DUMMY2) { + if (argc) { + argc--; argv++; + } else { + error("No parameter left for kDisplay(0x73)"); + } + } + break; default: - warning("Unknown kDisplay argument %X", displayArg); + if ((g_sci->getGameId() == GID_ISLANDBRAIN) && (g_sci->getEngineState()->currentRoomNumber() == 300)) + break; // WORKAROUND: we are called there with an forwarded 0 as additional parameter (script bug) + error("Unknown kDisplay argument %X", displayArg); break; } } @@ -540,14 +570,20 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { uint16 tTop = currport->curTop; uint16 tLeft = currport->curLeft; if (!g_sci->_features->usesOldGfxFunctions()) { - // Restore port settings for some SCI0LATE and SCI01+ only - // the change actually happened inbetween .530 (hoyle1) and .566 (heros quest). We don't have any detection for - // that currently, so we are using oldGfxFunctions (.502). The only games that could get regressions because of - // this are hoyle1, kq4 and funseeker. If there are regressions, we should use interpreter version (which would - // require exe version detection) - // If we restore the port for whole SCI0LATE, at least sq3old will get an issue - font 0 will get used when - // scanning for planets instead of font 600 - a setfont parameter is missing in one of the kDisplay calls in - // script 19. I assume this is a script bug, because it was added in sq3new. + // Restore port settings for some SCI0LATE and SCI01+ only. + // + // The change actually happened inbetween .530 (hoyle1) and .566 (heros + // quest). We don't have any detection for that currently, so we are + // using oldGfxFunctions (.502). The only games that could get + // regressions because of this are hoyle1, kq4 and funseeker. If there + // are regressions, we should use interpreter version (which would + // require exe version detection). + // + // If we restore the port for whole SCI0LATE, at least sq3old will get + // an issue - font 0 will get used when scanning for planets instead of + // font 600 - a setfont parameter is missing in one of the kDisplay + // calls in script 19. I assume this is a script bug, because it was + // added in sq3new. *currport = oldPort; } currport->curTop = tTop; @@ -562,12 +598,33 @@ void GfxPaint16::kernelShakeScreen(uint16 shakeCount, uint16 directions) { _screen->setVerticalShakePos(10); // TODO: horizontal shakes g_system->updateScreen(); - _gui->wait(3); + g_sci->getEngineState()->wait(3); + if (directions & SCI_SHAKE_DIRECTION_VERTICAL) _screen->setVerticalShakePos(0); + g_system->updateScreen(); - _gui->wait(3); + g_sci->getEngineState()->wait(3); } } +reg_t GfxPaint16::kernelPortraitLoad(const Common::String &resourceName) { + //Portrait *myPortrait = new Portrait(g_sci->getResMan(), _screen, _palette, resourceName); + return NULL_REG; +} + +void GfxPaint16::kernelPortraitShow(const Common::String &resourceName, Common::Point position, uint16 resourceId, uint16 noun, uint16 verb, uint16 cond, uint16 seq) { + Portrait *myPortrait = new Portrait(g_sci->getResMan(), g_sci->getEventManager(), _screen, _palette, _audio, resourceName); + // TODO: cache portraits + // adjust given coordinates to curPort (but dont adjust coordinates on upscaledHires_Save_Box and give us hires coordinates + // on kDrawCel, yeah this whole stuff makes sense) + position.x += _ports->getPort()->left; position.y += _ports->getPort()->top; + _screen->adjustToUpscaledCoordinates(position.y, position.x); + myPortrait->doit(position, resourceId, noun, verb, cond, seq); + delete myPortrait; +} + +void GfxPaint16::kernelPortraitUnload(uint16 portraitId) { +} + } // End of namespace Sci diff --git a/engines/sci/graphics/paint16.h b/engines/sci/graphics/paint16.h index 65f9dd0d9c..4c3ac255c4 100644 --- a/engines/sci/graphics/paint16.h +++ b/engines/sci/graphics/paint16.h @@ -26,7 +26,6 @@ #ifndef SCI_GRAPHICS_PAINT16_H #define SCI_GRAPHICS_PAINT16_H -#include "sci/graphics/gui.h" #include "sci/graphics/paint.h" #include "common/hashmap.h" @@ -45,7 +44,7 @@ class GfxView; */ class GfxPaint16 : public GfxPaint { public: - GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, SciGui *gui, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions); + GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions, AudioPlayer *audio); ~GfxPaint16(); void init(GfxAnimate *animate, GfxText16 *text16); @@ -54,8 +53,8 @@ public: void drawPicture(GuiResourceId pictureId, int16 animationNr, bool mirroredFlag, bool addToFlag, GuiResourceId paletteId); void drawCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo, uint16 scaleX = 128, uint16 scaleY = 128); - void drawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX = 128, uint16 scaleY = 128); - void drawCel(GfxView *view, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX = 128, uint16 scaleY = 128); + void drawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, const Common::Rect &celRect, byte priority, uint16 paletteNo, uint16 scaleX = 128, uint16 scaleY = 128); + void drawCel(GfxView *view, int16 loopNo, int16 celNo, const Common::Rect &celRect, byte priority, uint16 paletteNo, uint16 scaleX = 128, uint16 scaleY = 128); void drawHiresCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo, reg_t upscaledHiresHandle, uint16 scaleX = 128, uint16 scaleY = 128); void clearScreen(byte color = 255); @@ -76,26 +75,30 @@ public: void kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, bool animationBlackoutFlag, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo); void kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle); - void kernelGraphFillBoxForeground(Common::Rect rect); - void kernelGraphFillBoxBackground(Common::Rect rect); - void kernelGraphFillBox(Common::Rect rect, uint16 colorMask, int16 color, int16 priority, int16 control); - void kernelGraphFrameBox(Common::Rect rect, int16 color); + void kernelGraphFillBoxForeground(const Common::Rect &rect); + void kernelGraphFillBoxBackground(const Common::Rect &rect); + void kernelGraphFillBox(const Common::Rect &rect, uint16 colorMask, int16 color, int16 priority, int16 control); + void kernelGraphFrameBox(const Common::Rect &rect, int16 color); void kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control); - reg_t kernelGraphSaveBox(Common::Rect rect, uint16 flags); - reg_t kernelGraphSaveUpscaledHiresBox(Common::Rect rect); + reg_t kernelGraphSaveBox(const Common::Rect &rect, uint16 flags); + reg_t kernelGraphSaveUpscaledHiresBox(const Common::Rect &rect); void kernelGraphRestoreBox(reg_t handle); - void kernelGraphUpdateBox(Common::Rect rect, bool hiresMode); + void kernelGraphUpdateBox(const Common::Rect &rect, bool hiresMode); void kernelGraphRedrawBox(Common::Rect rect); reg_t kernelDisplay(const char *text, int argc, reg_t *argv); void kernelShakeScreen(uint16 shakeCount, uint16 directions); + reg_t kernelPortraitLoad(const Common::String &resourceName); + void kernelPortraitShow(const Common::String &resourceName, Common::Point position, uint16 resourceNum, uint16 noun, uint16 verb, uint16 cond, uint16 seq); + void kernelPortraitUnload(uint16 portraitId); + private: ResourceManager *_resMan; SegManager *_segMan; Kernel *_kernel; - SciGui *_gui; + AudioPlayer *_audio; GfxAnimate *_animate; GfxCache *_cache; GfxPorts *_ports; diff --git a/engines/sci/graphics/paint32.cpp b/engines/sci/graphics/paint32.cpp index 711efc9816..9b24da413b 100644 --- a/engines/sci/graphics/paint32.cpp +++ b/engines/sci/graphics/paint32.cpp @@ -38,6 +38,7 @@ #include "sci/graphics/view.h" #include "sci/graphics/screen.h" #include "sci/graphics/palette.h" +#include "sci/graphics/robot.h" namespace Sci { @@ -79,4 +80,10 @@ void GfxPaint32::kernelGraphDrawLine(Common::Point startPoint, Common::Point end _screen->drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y, color, priority, control); } +void GfxPaint32::debugDrawRobot(GuiResourceId robotId) { + GfxRobot *test = new GfxRobot(g_sci->getResMan(), _screen, robotId); + test->draw(); + delete test; +} + } // End of namespace Sci diff --git a/engines/sci/graphics/paint32.h b/engines/sci/graphics/paint32.h index f4d6340361..a048d7f307 100644 --- a/engines/sci/graphics/paint32.h +++ b/engines/sci/graphics/paint32.h @@ -26,7 +26,6 @@ #ifndef SCI_GRAPHICS_PAINT32_H #define SCI_GRAPHICS_PAINT32_H -#include "sci/graphics/gui.h" #include "sci/graphics/paint.h" #include "common/hashmap.h" @@ -49,6 +48,8 @@ public: void kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle); void kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control); + void debugDrawRobot(GuiResourceId robotId); + private: ResourceManager *_resMan; SegManager *_segMan; diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 3c4cf7e964..957199f8b9 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -30,13 +30,15 @@ #include "sci/sci.h" #include "sci/engine/state.h" +#include "sci/graphics/cache.h" #include "sci/graphics/maciconbar.h" #include "sci/graphics/palette.h" #include "sci/graphics/screen.h" +#include "sci/graphics/view.h" namespace Sci { -GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen, bool autoSetPalette) +GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen, bool useMerging) : _resMan(resMan), _screen(screen) { int16 color; @@ -57,23 +59,39 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen, bool autoSetP _sysPalette.colors[255].b = 255; _sysPaletteChanged = false; - if (autoSetPalette) { - if (_resMan->getViewType() == kViewEga) - setEGA(); - else if (_resMan->isAmiga32color()) - setAmiga(); - else - kernelSetFromResource(999, true); - } + + // Pseudo-WORKAROUND + // Quest for Glory 3 demo, Eco Quest 1 demo, Laura Bow 2 demo, Police Quest 1 vga and all Nick's Picks + // all use an inbetween interpreter, some parts are SCI1.1, some parts are SCI1 + // It's not using the SCI1.1 palette merging (copying over all the colors) but the real merging + // If we use the copying over, we will get issues because some views have marked all colors as being used + // and those will overwrite the current palette in that case + _useMerging = useMerging; + + palVaryInit(); } GfxPalette::~GfxPalette() { } +bool GfxPalette::isMerging() { + return _useMerging; +} + +// meant to get called only once during init of engine +void GfxPalette::setDefault() { + if (_resMan->getViewType() == kViewEga) + setEGA(); + else if (_resMan->isAmiga32color()) + setAmiga(); + else + kernelSetFromResource(999, true); +} + #define SCI_PAL_FORMAT_CONSTANT 1 #define SCI_PAL_FORMAT_VARIABLE 0 -void GfxPalette::createFromData(byte *data, Palette *paletteOut) { +void GfxPalette::createFromData(byte *data, int bytesLeft, Palette *paletteOut) { int palFormat = 0; int palOffset = 0; int palColorStart = 0; @@ -81,10 +99,16 @@ void GfxPalette::createFromData(byte *data, Palette *paletteOut) { int colorNo = 0; memset(paletteOut, 0, sizeof(Palette)); - // Setup default mapping + // Setup 1:1 mapping for (colorNo = 0; colorNo < 256; colorNo++) { paletteOut->mapping[colorNo] = colorNo; } + if (bytesLeft < 37) { + // This happens when loading palette of picture 0 in sq5 - the resource is broken and doesn't contain a full + // palette + warning("GfxPalette::createFromData() - not enough bytes in resource, expected palette header"); + return; + } if ((data[0] == 0 && data[1] == 1) || (data[0] == 0 && data[1] == 0 && READ_LE_UINT16(data + 29) == 0)) { // SCI0/SCI1 palette palFormat = SCI_PAL_FORMAT_VARIABLE; // CONSTANT; @@ -99,6 +123,11 @@ void GfxPalette::createFromData(byte *data, Palette *paletteOut) { } switch (palFormat) { case SCI_PAL_FORMAT_CONSTANT: + // Check, if enough bytes left + if (bytesLeft < palOffset + (3 * palColorCount)) { + warning("GfxPalette::createFromData() - not enough bytes in resource, expected palette colors"); + return; + } for (colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) { paletteOut->colors[colorNo].used = 1; paletteOut->colors[colorNo].r = data[palOffset++]; @@ -107,6 +136,10 @@ void GfxPalette::createFromData(byte *data, Palette *paletteOut) { } break; case SCI_PAL_FORMAT_VARIABLE: + if (bytesLeft < palOffset + (4 * palColorCount)) { + warning("GfxPalette::createFromData() - not enough bytes in resource, expected palette colors"); + return; + } for (colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) { paletteOut->colors[colorNo].used = data[palOffset++]; paletteOut->colors[colorNo].r = data[palOffset++]; @@ -180,112 +213,144 @@ void GfxPalette::setEGA() { // Now setting colors 16-254 to the correct mix colors that occur when not doing a dithering run on // finished pictures for (curColor = 0x10; curColor <= 0xFE; curColor++) { - _sysPalette.colors[curColor].used = curColor; + _sysPalette.colors[curColor].used = 1; color1 = curColor & 0x0F; color2 = curColor >> 4; _sysPalette.colors[curColor].r = (_sysPalette.colors[color1].r >> 1) + (_sysPalette.colors[color2].r >> 1); _sysPalette.colors[curColor].g = (_sysPalette.colors[color1].g >> 1) + (_sysPalette.colors[color2].g >> 1); _sysPalette.colors[curColor].b = (_sysPalette.colors[color1].b >> 1) + (_sysPalette.colors[color2].b >> 1); } + _sysPalette.timestamp = 1; setOnScreen(); } -void GfxPalette::set(Palette *sciPal, bool force, bool forceRealMerge) { +void GfxPalette::set(Palette *newPalette, bool force, bool forceRealMerge) { uint32 systime = _sysPalette.timestamp; - if (force || sciPal->timestamp != systime) { - _sysPaletteChanged |= merge(sciPal, &_sysPalette, force, forceRealMerge); - sciPal->timestamp = _sysPalette.timestamp; - if (_sysPaletteChanged && _screen->_picNotValid == 0) { // && systime != _sysPalette.timestamp) { - // Removed timestamp checking, because this shouldnt be needed anymore. I'm leaving it commented just in - // case this causes regressions + if (force || newPalette->timestamp != systime) { + // SCI1.1+ doesnt do real merging anymore, but simply copying over the used colors from other palettes + // There are some games with inbetween SCI1.1 interpreters, use real merging for them (e.g. laura bow 2 demo) + if ((forceRealMerge) || (_useMerging)) + _sysPaletteChanged |= merge(newPalette, force, forceRealMerge); + else + _sysPaletteChanged |= insert(newPalette, &_sysPalette); + + // Adjust timestamp on newPalette, so it wont get merged/inserted w/o need + newPalette->timestamp = _sysPalette.timestamp; + + bool updatePalette = _sysPaletteChanged && _screen->_picNotValid == 0; + + if (_palVaryResourceId != -1) { + // Pal-vary currently active, we don't set at any time, but also insert into origin palette + insert(newPalette, &_palVaryOriginPalette); + palVaryProcess(0, updatePalette); + return; + } + + if (updatePalette) { setOnScreen(); _sysPaletteChanged = false; } } } -bool GfxPalette::merge(Palette *pFrom, Palette *pTo, bool force, bool forceRealMerge) { +bool GfxPalette::insert(Palette *newPalette, Palette *destPalette) { + bool paletteChanged = false; + + for (int i = 1; i < 255; i++) { + if (newPalette->colors[i].used) { + if ((newPalette->colors[i].r != destPalette->colors[i].r) || (newPalette->colors[i].g != destPalette->colors[i].g) || (newPalette->colors[i].b != destPalette->colors[i].b)) { + destPalette->colors[i].r = newPalette->colors[i].r; + destPalette->colors[i].g = newPalette->colors[i].g; + destPalette->colors[i].b = newPalette->colors[i].b; + paletteChanged = true; + } + destPalette->colors[i].used = newPalette->colors[i].used; + newPalette->mapping[i] = i; + } + } + // We don't update the timestamp for SCI1.1, it's only updated on kDrawPic calls + return paletteChanged; +} + +bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) { uint16 res; int i,j; bool paletteChanged = false; - if ((!forceRealMerge) && (getSciVersion() >= SCI_VERSION_1_1)) { - // SCI1.1+ doesnt do real merging anymore, but simply copying over the used colors from other palettes - for (i = 1; i < 255; i++) { - if (pFrom->colors[i].used) { - if ((pFrom->colors[i].r != pTo->colors[i].r) || (pFrom->colors[i].g != pTo->colors[i].g) || (pFrom->colors[i].b != pTo->colors[i].b)) { - pTo->colors[i].r = pFrom->colors[i].r; - pTo->colors[i].g = pFrom->colors[i].g; - pTo->colors[i].b = pFrom->colors[i].b; - paletteChanged = true; - } - pTo->colors[i].used = pFrom->colors[i].used; - pFrom->mapping[i] = i; + // colors 0 (black) and 255 (white) are not affected by merging + for (i = 1 ; i < 255; i++) { + if (!newPalette->colors[i].used)// color is not used - so skip it + continue; + // forced palette merging or dest color is not used yet + if (force || (!_sysPalette.colors[i].used)) { + _sysPalette.colors[i].used = newPalette->colors[i].used; + if ((newPalette->colors[i].r != _sysPalette.colors[i].r) || (newPalette->colors[i].g != _sysPalette.colors[i].g) || (newPalette->colors[i].b != _sysPalette.colors[i].b)) { + _sysPalette.colors[i].r = newPalette->colors[i].r; + _sysPalette.colors[i].g = newPalette->colors[i].g; + _sysPalette.colors[i].b = newPalette->colors[i].b; + paletteChanged = true; } + newPalette->mapping[i] = i; + continue; } - } else { - // colors 0 (black) and 255 (white) are not affected by merging - for (i = 1 ; i < 255; i++) { - if (!pFrom->colors[i].used)// color is not used - so skip it - continue; - // forced palette merging or dest color is not used yet - if (force || (!pTo->colors[i].used)) { - pTo->colors[i].used = pFrom->colors[i].used; - if ((pFrom->colors[i].r != pTo->colors[i].r) || (pFrom->colors[i].g != pTo->colors[i].g) || (pFrom->colors[i].b != pTo->colors[i].b)) { - pTo->colors[i].r = pFrom->colors[i].r; - pTo->colors[i].g = pFrom->colors[i].g; - pTo->colors[i].b = pFrom->colors[i].b; - paletteChanged = true; - } - pFrom->mapping[i] = i; - continue; - } - // is the same color already at the same position? -> match it directly w/o lookup - // this fixes games like lsl1demo/sq5 where the same rgb color exists multiple times and where we would - // otherwise match the wrong one (which would result into the pixels affected (or not) by palette changes) - if ((pTo->colors[i].r == pFrom->colors[i].r) && (pTo->colors[i].g == pFrom->colors[i].g) && (pTo->colors[i].b == pFrom->colors[i].b)) { - pFrom->mapping[i] = i; - continue; - } - // check if exact color could be matched - res = matchColor(pTo, pFrom->colors[i].r, pFrom->colors[i].g, pFrom->colors[i].b); - if (res & 0x8000) { // exact match was found - pFrom->mapping[i] = res & 0xFF; - continue; - } - // no exact match - see if there is an unused color - for (j = 1; j < 256; j++) - if (!pTo->colors[j].used) { - pTo->colors[j].used = pFrom->colors[i].used; - pTo->colors[j].r = pFrom->colors[i].r; - pTo->colors[j].g = pFrom->colors[i].g; - pTo->colors[j].b = pFrom->colors[i].b; - pFrom->mapping[i] = j; - paletteChanged = true; - break; - } - // if still no luck - set an approximate color - if (j == 256) { - pFrom->mapping[i] = res & 0xFF; - pTo->colors[res & 0xFF].used |= 0x10; + // is the same color already at the same position? -> match it directly w/o lookup + // this fixes games like lsl1demo/sq5 where the same rgb color exists multiple times and where we would + // otherwise match the wrong one (which would result into the pixels affected (or not) by palette changes) + if ((_sysPalette.colors[i].r == newPalette->colors[i].r) && (_sysPalette.colors[i].g == newPalette->colors[i].g) && (_sysPalette.colors[i].b == newPalette->colors[i].b)) { + newPalette->mapping[i] = i; + continue; + } + // check if exact color could be matched + res = matchColor(newPalette->colors[i].r, newPalette->colors[i].g, newPalette->colors[i].b); + if (res & 0x8000) { // exact match was found + newPalette->mapping[i] = res & 0xFF; + continue; + } + // no exact match - see if there is an unused color + for (j = 1; j < 256; j++) + if (!_sysPalette.colors[j].used) { + _sysPalette.colors[j].used = newPalette->colors[i].used; + _sysPalette.colors[j].r = newPalette->colors[i].r; + _sysPalette.colors[j].g = newPalette->colors[i].g; + _sysPalette.colors[j].b = newPalette->colors[i].b; + newPalette->mapping[i] = j; + paletteChanged = true; + break; } + // if still no luck - set an approximate color + if (j == 256) { + newPalette->mapping[i] = res & 0xFF; + _sysPalette.colors[res & 0xFF].used |= 0x10; } } - pTo->timestamp = g_system->getMillis() * 60 / 1000; + + if (!forceRealMerge) + _sysPalette.timestamp = g_system->getMillis() * 60 / 1000; return paletteChanged; } -uint16 GfxPalette::matchColor(Palette *pPal, byte r, byte g, byte b) { +// This is called for SCI1.1, when kDrawPic got done. We update sysPalette timestamp this way for SCI1.1 and also load +// target-palette, if palvary is active +void GfxPalette::drewPicture(GuiResourceId pictureId) { + if (!_useMerging) // Don't do this on inbetween SCI1.1 games + _sysPalette.timestamp++; + + if (_palVaryResourceId != -1) { + palVaryLoadTargetPalette(pictureId); + } +} + +uint16 GfxPalette::matchColor(byte r, byte g, byte b) { byte found = 0xFF; int diff = 0x2FFFF, cdiff; int16 dr,dg,db; for (int i = 1; i < 255; i++) { - if ((!pPal->colors[i].used)) + if ((!_sysPalette.colors[i].used)) continue; - dr = pPal->colors[i].r - r; - dg = pPal->colors[i].g - g; - db = pPal->colors[i].b - b; + dr = _sysPalette.colors[i].r - r; + dg = _sysPalette.colors[i].g - g; + db = _sysPalette.colors[i].b - b; // minimum squares match cdiff = (dr*dr) + (dg*dg) + (db*db); // minimum sum match (Sierra's) @@ -306,8 +371,6 @@ void GfxPalette::getSys(Palette *pal) { } void GfxPalette::setOnScreen() { -// if (pal != &_sysPalette) -// memcpy(&_sysPalette,pal,sizeof(Palette)); // We dont change palette at all times for amiga if (_resMan->isAmiga32color()) return; @@ -319,11 +382,11 @@ void GfxPalette::setOnScreen() { } bool GfxPalette::kernelSetFromResource(GuiResourceId resourceId, bool force) { - Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), 0); + Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false); Palette palette; if (palResource) { - createFromData(palResource->data, &palette); + createFromData(palResource->data, palResource->size, &palette); set(&palette, force); return true; } @@ -346,12 +409,18 @@ void GfxPalette::kernelUnsetFlag(uint16 fromColor, uint16 toColor, uint16 flag) void GfxPalette::kernelSetIntensity(uint16 fromColor, uint16 toColor, uint16 intensity, bool setPalette) { memset(&_sysPalette.intensity[0] + fromColor, intensity, toColor - fromColor); - if (setPalette) + if (setPalette) { setOnScreen(); + EngineState *state = g_sci->getEngineState(); + // Call speed throttler from here as well just in case we need it + // At least in kq6 intro the scripts call us in a tight loop for fadein/fadeout + state->speedThrottler(30); + state->_throttleTrigger = true; + } } int16 GfxPalette::kernelFindColor(uint16 r, uint16 g, uint16 b) { - return matchColor(&_sysPalette, r, g, b) & 0xFF; + return matchColor(r, g, b) & 0xFF; } // Returns true, if palette got changed @@ -378,6 +447,8 @@ bool GfxPalette::kernelAnimate(byte fromColor, byte toColor, int speed) { scheduleCount++; } + g_sci->getEngineState()->_throttleTrigger = true; + for (scheduleNr = 0; scheduleNr < scheduleCount; scheduleNr++) { if (_schedules[scheduleNr].from == fromColor) { if (_schedules[scheduleNr].schedule <= now) { @@ -414,7 +485,21 @@ void GfxPalette::kernelAnimateSet() { } void GfxPalette::kernelAssertPalette(GuiResourceId resourceId) { - warning("kAssertPalette %d", resourceId); + // Sometimes invalid viewIds are asked for, ignore those (e.g. qfg1vga) + //if (!_resMan->testResource(ResourceId(kResourceTypeView, resourceId))) + // return; + // maybe we took the wrong parameter before, if this causes invalid view again, enable to commented out code again + + GfxView *view = g_sci->_gfxCache->getView(resourceId); + Palette *viewPalette = view->getPalette(); + if (viewPalette) { + // merge/insert this palette + set(viewPalette, true); + } +} + +void GfxPalette::kernelSyncScreenPalette() { + _screen->getPalette(&_sysPalette); } // palVary @@ -443,40 +528,191 @@ void GfxPalette::kernelAssertPalette(GuiResourceId resourceId) { // Saving/restoring // need to save start and target-palette, when palVaryOn = true -void GfxPalette::startPalVary(uint16 paletteId, uint16 ticks) { - kernelSetFromResource(paletteId, true); - return; +void GfxPalette::palVaryInit() { + _palVaryResourceId = -1; + _palVaryPaused = 0; + _palVarySignal = 0; + _palVaryStep = 0; + _palVaryStepStop = 0; + _palVaryDirection = 0; + _palVaryTicks = 0; +} - if (_palVaryId >= 0) // another palvary is taking place, return - return; +bool GfxPalette::palVaryLoadTargetPalette(GuiResourceId resourceId) { + _palVaryResourceId = resourceId; + Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false); + if (palResource) { + // Load and initialize destination palette + createFromData(palResource->data, palResource->size, &_palVaryTargetPalette); + return true; + } + return false; +} + +void GfxPalette::palVaryInstallTimer() { + int16 ticks = _palVaryTicks > 0 ? _palVaryTicks : 1; + // Call signal increase every [ticks] + g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000000 / 60 * ticks, this); +} + +void GfxPalette::palVaryRemoveTimer() { + g_sci->getTimerManager()->removeTimerProc(&palVaryCallback); +} + +bool GfxPalette::kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stepStop, uint16 direction) { + if (_palVaryResourceId != -1) // another palvary is taking place, return + return false; + + if (palVaryLoadTargetPalette(resourceId)) { + // Save current palette + memcpy(&_palVaryOriginPalette, &_sysPalette, sizeof(Palette)); + + _palVarySignal = 0; + _palVaryTicks = ticks; + _palVaryStep = 1; + _palVaryStepStop = stepStop; + _palVaryDirection = direction; + // if no ticks are given, jump directly to destination + if (!_palVaryTicks) + _palVaryDirection = stepStop; + palVaryInstallTimer(); + return true; + } + return false; +} + +int16 GfxPalette::kernelPalVaryReverse(int16 ticks, uint16 stepStop, int16 direction) { + if (_palVaryResourceId == -1) + return 0; + + if (_palVaryStep > 64) + _palVaryStep = 64; + if (ticks != -1) + _palVaryTicks = ticks; + _palVaryStepStop = stepStop; + _palVaryDirection = direction != -1 ? -direction : -_palVaryDirection; + + if (!_palVaryTicks) + _palVaryDirection = _palVaryStepStop - _palVaryStep; + palVaryInstallTimer(); + return kernelPalVaryGetCurrentStep(); +} + +int16 GfxPalette::kernelPalVaryGetCurrentStep() { + if (_palVaryDirection >= 0) + return _palVaryStep; + return -_palVaryStep; +} + +int16 GfxPalette::kernelPalVaryChangeTarget(GuiResourceId resourceId) { + if (_palVaryResourceId != -1) { + Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false); + if (palResource) { + Palette insertPalette; + createFromData(palResource->data, palResource->size, &insertPalette); + // insert new palette into target + insert(&insertPalette, &_palVaryTargetPalette); + // update palette and set on screen + palVaryProcess(0, true); + } + } + return kernelPalVaryGetCurrentStep(); +} - _palVaryId = paletteId; - _palVaryStart = g_system->getMillis(); - _palVaryEnd = _palVaryStart + ticks * 1000 / 60; - g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000 / 60, this); +void GfxPalette::kernelPalVaryChangeTicks(uint16 ticks) { + _palVaryTicks = ticks; + if (_palVaryStep - _palVaryStepStop) { + palVaryRemoveTimer(); + palVaryInstallTimer(); + } } -void GfxPalette::togglePalVary(bool pause) { +void GfxPalette::kernelPalVaryPause(bool pause) { + if (_palVaryResourceId == -1) + return; // this call is actually counting states, so calling this 3 times with true will require calling it later // 3 times with false to actually remove pause - - // TODO + if (pause) { + _palVaryPaused++; + } else { + if (_palVaryPaused) + _palVaryPaused--; + } } -void GfxPalette::stopPalVary() { - g_sci->getTimerManager()->removeTimerProc(&palVaryCallback); - _palVaryId = -1; // invalidate the target palette +void GfxPalette::kernelPalVaryDeinit() { + palVaryRemoveTimer(); - // HACK: just set the target palette - kernelSetFromResource(_palVaryId, true); + _palVaryResourceId = -1; // invalidate the target palette } void GfxPalette::palVaryCallback(void *refCon) { - ((GfxPalette *)refCon)->doPalVary(); + ((GfxPalette *)refCon)->palVaryIncreaseSignal(); +} + +void GfxPalette::palVaryIncreaseSignal() { + if (!_palVaryPaused) + _palVarySignal++; +} + +// Actually do the pal vary processing +void GfxPalette::palVaryUpdate() { + if (_palVarySignal) { + palVaryProcess(_palVarySignal, true); + _palVarySignal = 0; + } +} + +void GfxPalette::palVaryPrepareForTransition() { + if (_palVaryResourceId != -1) { + // Before doing transitions, we have to prepare palette + palVaryProcess(0, false); + } } -void GfxPalette::doPalVary() { - // TODO: do palette transition here... +// Processes pal vary updates +void GfxPalette::palVaryProcess(int signal, bool setPalette) { + int16 stepChange = signal * _palVaryDirection; + + _palVaryStep += stepChange; + if (stepChange > 0) { + if (_palVaryStep > _palVaryStepStop) + _palVaryStep = _palVaryStepStop; + } else { + if (_palVaryStep < _palVaryStepStop) { + if (signal) + _palVaryStep = _palVaryStepStop; + } + } + + // We don't need updates anymore, if we reached end-position + if (_palVaryStep == _palVaryStepStop) + palVaryRemoveTimer(); + if (_palVaryStep == 0) + _palVaryResourceId = -1; + + // Calculate inbetween palette + Sci::Color inbetween; + int16 color; + for (int colorNr = 1; colorNr < 255; colorNr++) { + inbetween.used = _sysPalette.colors[colorNr].used; + color = _palVaryTargetPalette.colors[colorNr].r - _palVaryOriginPalette.colors[colorNr].r; + inbetween.r = ((color * _palVaryStep) / 64) + _palVaryOriginPalette.colors[colorNr].r; + color = _palVaryTargetPalette.colors[colorNr].g - _palVaryOriginPalette.colors[colorNr].g; + inbetween.g = ((color * _palVaryStep) / 64) + _palVaryOriginPalette.colors[colorNr].g; + color = _palVaryTargetPalette.colors[colorNr].b - _palVaryOriginPalette.colors[colorNr].b; + inbetween.b = ((color * _palVaryStep) / 64) + _palVaryOriginPalette.colors[colorNr].b; + + if (memcmp(&inbetween, &_sysPalette.colors[colorNr], sizeof(Sci::Color))) { + _sysPalette.colors[colorNr] = inbetween; + _sysPaletteChanged = true; + } + } + + if ((_sysPaletteChanged) && (setPalette) && (_screen->_picNotValid == 0)) { + setOnScreen(); + _sysPaletteChanged = false; + } } } // End of namespace Sci diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 46fec48739..6af1d5a490 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -36,20 +36,26 @@ class Screen; */ class GfxPalette { public: - GfxPalette(ResourceManager *resMan, GfxScreen *screen, bool autoSetPalette = true); + GfxPalette(ResourceManager *resMan, GfxScreen *screen, bool useMerging); ~GfxPalette(); - void createFromData(byte *data, Palette *paletteOut); + bool isMerging(); + + void setDefault(); + void createFromData(byte *data, int bytesLeft, Palette *paletteOut); bool setAmiga(); void modifyAmigaPalette(byte *data); void setEGA(); void set(Palette *sciPal, bool force, bool forceRealMerge = false); - bool merge(Palette *pFrom, Palette *pTo, bool force, bool forceRealMerge); - uint16 matchColor(Palette *pPal, byte r, byte g, byte b); + bool insert(Palette *newPalette, Palette *destPalette); + bool merge(Palette *pFrom, bool force, bool forceRealMerge); + uint16 matchColor(byte r, byte g, byte b); void getSys(Palette *pal); void setOnScreen(); + void drewPicture(GuiResourceId pictureId); + bool kernelSetFromResource(GuiResourceId resourceId, bool force); void kernelSetFlag(uint16 fromColor, uint16 toColor, uint16 flag); void kernelUnsetFlag(uint16 fromColor, uint16 toColor, uint16 flag); @@ -59,25 +65,46 @@ public: void kernelAnimateSet(); void kernelAssertPalette(GuiResourceId resourceId); - void startPalVary(uint16 paletteId, uint16 ticks); - void togglePalVary(bool pause); - void stopPalVary(); + void kernelSyncScreenPalette(); + + bool kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stepStop, uint16 direction); + int16 kernelPalVaryReverse(int16 ticks, uint16 stepStop, int16 direction); + int16 kernelPalVaryGetCurrentStep(); + int16 kernelPalVaryChangeTarget(GuiResourceId resourceId); + void kernelPalVaryChangeTicks(uint16 ticks); + void kernelPalVaryPause(bool pause); + void kernelPalVaryDeinit(); + void palVaryUpdate(); + void palVaryPrepareForTransition(); + void palVaryProcess(int signal, bool setPalette); Palette _sysPalette; private: + void palVaryInit(); + void palVaryInstallTimer(); + void palVaryRemoveTimer(); + bool palVaryLoadTargetPalette(GuiResourceId resourceId); static void palVaryCallback(void *refCon); - void doPalVary(); + void palVaryIncreaseSignal(); GfxScreen *_screen; ResourceManager *_resMan; - int16 _palVaryId; - uint32 _palVaryStart; - uint32 _palVaryEnd; bool _sysPaletteChanged; + bool _useMerging; Common::Array<PalSchedule> _schedules; + + GuiResourceId _palVaryResourceId; + Palette _palVaryOriginPalette; + Palette _palVaryTargetPalette; + int16 _palVaryStep; + int16 _palVaryStepStop; + int16 _palVaryDirection; + uint16 _palVaryTicks; + int _palVaryPaused; + int _palVarySignal; }; } // End of namespace Sci diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp index a59153f116..7cd37b6f46 100644 --- a/engines/sci/graphics/picture.cpp +++ b/engines/sci/graphics/picture.cpp @@ -109,7 +109,7 @@ void GfxPicture::drawSci11Vga() { Palette palette; // Create palette and set it - _palette->createFromData(inbuffer + palette_data_ptr, &palette); + _palette->createFromData(inbuffer + palette_data_ptr, size - palette_data_ptr, &palette); _palette->set(&palette, true); // display Cel-data @@ -147,7 +147,7 @@ void GfxPicture::drawSci32Vga(int16 celNo) { if ((celNo == -1) || (celNo == 0)) { // Create palette and set it - _palette->createFromData(inbuffer + palette_data_ptr, &palette); + _palette->createFromData(inbuffer + palette_data_ptr, size - palette_data_ptr, &palette); _palette->set(&palette, true); } if (celNo != -1) { @@ -437,7 +437,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) { memcpy(&EGApalettes[i], &vector_defaultEGApalette, sizeof(vector_defaultEGApalette)); memcpy(&EGApriority, &vector_defaultEGApriority, sizeof(vector_defaultEGApriority)); - if (strcmp(g_sci->getGameID(), "iceman") == 0) { + if (g_sci->getGameId() == GID_ICEMAN) { // WORKAROUND: we remove certain visual&priority lines in underwater rooms of iceman, when not dithering the // picture. Normally those lines aren't shown, because they share the same color as the dithered // fill color combination. When not dithering, those lines would appear and get distracting. @@ -532,7 +532,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) { // inside picture data for such games case PIC_OP_SET_PATTERN: if (_resourceType >= SCI_PICTURE_TYPE_SCI11) { - if (strcmp(g_sci->getGameID(), "sq4") == 0) { + if (g_sci->getGameId() == GID_SQ4) { // WORKAROUND: For SQ4 / for some pictures handle this like a terminator // This picture includes garbage data, first a set pattern w/o parameter and then short pattern // I guess that garbage is a left over from the sq4-floppy (sci1) to sq4-cd (sci1.1) conversion diff --git a/engines/sci/graphics/portrait.cpp b/engines/sci/graphics/portrait.cpp index 1208f8ed65..8f4fe094a8 100644 --- a/engines/sci/graphics/portrait.cpp +++ b/engines/sci/graphics/portrait.cpp @@ -23,6 +23,7 @@ * */ +#include "common/archive.h" #include "common/util.h" #include "common/stack.h" #include "graphics/primitives.h" @@ -30,7 +31,6 @@ #include "sci/sci.h" #include "sci/event.h" #include "sci/engine/state.h" -#include "sci/graphics/gui.h" #include "sci/graphics/screen.h" #include "sci/graphics/palette.h" #include "sci/graphics/portrait.h" @@ -38,8 +38,8 @@ namespace Sci { -Portrait::Portrait(ResourceManager *resMan, SciEvent *event, SciGui *gui, GfxScreen *screen, GfxPalette *palette, AudioPlayer *audio, Common::String resourceName) - : _resMan(resMan), _event(event), _gui(gui), _screen(screen), _palette(palette), _audio(audio), _resourceName(resourceName) { +Portrait::Portrait(ResourceManager *resMan, EventManager *event, GfxScreen *screen, GfxPalette *palette, AudioPlayer *audio, Common::String resourceName) + : _resMan(resMan), _event(event), _screen(screen), _palette(palette), _audio(audio), _resourceName(resourceName) { init(); } @@ -166,7 +166,7 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint // Do animation depending on sync resource till audio is done playing uint16 syncCue; int timerPosition, curPosition; - sciEvent curEvent; + SciEvent curEvent; bool userAbort = false; while ((syncOffset < syncResource->size - 2) && (!userAbort)) { @@ -181,8 +181,8 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint // Wait till syncTime passed, then show specific animation bitmap do { - _gui->wait(1); - curEvent = _event->get(SCI_EVENT_ANY); + g_sci->getEngineState()->wait(1); + curEvent = _event->getSciEvent(SCI_EVENT_ANY); if (curEvent.type == SCI_EVENT_MOUSE_PRESS || (curEvent.type == SCI_EVENT_KEYBOARD && curEvent.data == SCI_KEY_ESC) || g_engine->shouldQuit()) diff --git a/engines/sci/graphics/portrait.h b/engines/sci/graphics/portrait.h index 4b22e209a3..7da9425c9d 100644 --- a/engines/sci/graphics/portrait.h +++ b/engines/sci/graphics/portrait.h @@ -42,7 +42,7 @@ struct PortraitBitmap { */ class Portrait { public: - Portrait(ResourceManager *resMan, SciEvent *event, SciGui *gui, GfxScreen *screen, GfxPalette *palette, AudioPlayer *audio, Common::String resourceName); + Portrait(ResourceManager *resMan, EventManager *event, GfxScreen *screen, GfxPalette *palette, AudioPlayer *audio, Common::String resourceName); ~Portrait(); void setupAudio(uint16 resourceId, uint16 noun, uint16 verb, uint16 cond, uint16 seq); @@ -56,8 +56,7 @@ private: void bitsShow(); ResourceManager *_resMan; - SciEvent *_event; - SciGui *_gui; + EventManager *_event; GfxPalette *_palette; GfxScreen *_screen; AudioPlayer *_audio; diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index cdb6fe4ae1..611db1061a 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -54,11 +54,10 @@ GfxPorts::~GfxPorts() { delete _menuPort; } -void GfxPorts::init(bool usesOldGfxFunctions, SciGui *gui, GfxPaint16 *paint16, GfxText16 *text16) { +void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *text16) { int16 offTop = 10; _usesOldGfxFunctions = usesOldGfxFunctions; - _gui = gui; _paint16 = paint16; _text16 = text16; @@ -85,20 +84,44 @@ void GfxPorts::init(bool usesOldGfxFunctions, SciGui *gui, GfxPaint16 *paint16, else _styleUser = SCI_WINDOWMGR_STYLE_USER | SCI_WINDOWMGR_STYLE_TRANSPARENT; - // Jones, Slater and Hoyle 3 were called with parameter -Nw 0 0 200 320. - // Mother Goose (SCI1) uses -Nw 0 0 159 262. The game will later use SetPort so we don't need to set the other fields. + // Jones, Slater, Hoyle 3&4 and Crazy Nicks Laura Bow/Kings Quest were + // called with parameter -Nw 0 0 200 320. + // Mother Goose (SCI1) uses -Nw 0 0 159 262. The game will later use + // SetPort so we don't need to set the other fields. // This actually meant not skipping the first 10 pixellines in windowMgrPort - Common::String gameId = g_sci->getGameID(); - if (gameId == "jones" || gameId == "slater" || gameId == "hoyle3" || (gameId == "mothergoose" && getSciVersion() == SCI_VERSION_1_EARLY)) + switch (g_sci->getGameId()) { + case GID_JONES: + case GID_SLATER: + case GID_HOYLE3: + case GID_HOYLE4: + case GID_CNICK_LAURABOW: + case GID_CNICK_KQ: offTop = 0; + break; + case GID_MOTHERGOOSE: + if (getSciVersion() == SCI_VERSION_1_EARLY) + offTop = 0; + break; + case GID_FAIRYTALES: + // Mixed-Up Fairy Tales (& its demo) uses -w 26 0 200 320. If we don't + // also do this we will get not-fully-removed windows everywhere. + offTop = 26; + break; + default: + offTop = 10; + break; + } openPort(_wmgrPort); setPort(_wmgrPort); // SCI0 games till kq4 (.502 - not including) did not adjust against _wmgrPort in kNewWindow // We leave _wmgrPort top at 0, so the adjustment wont get done - if (!g_sci->_features->usesOldGfxFunctions()) + if (!g_sci->_features->usesOldGfxFunctions()) { setOrigin(0, offTop); - _wmgrPort->rect.bottom = _screen->getHeight() - offTop; + _wmgrPort->rect.bottom = _screen->getHeight() - offTop; + } else { + _wmgrPort->rect.bottom = _screen->getHeight(); + } _wmgrPort->rect.right = _screen->getWidth(); _wmgrPort->rect.moveTo(0, 0); _wmgrPort->curTop = 0; @@ -214,7 +237,7 @@ Window *GfxPorts::newWindow(const Common::Rect &dims, const Common::Rect *restor Common::Rect r; if (!pwnd) { - warning("Can't open window!"); + error("Can't open window!"); return 0; } @@ -228,6 +251,7 @@ Window *GfxPorts::newWindow(const Common::Rect &dims, const Common::Rect *restor r = dims; if (r.width() > _screen->getWidth()) { // We get invalid dimensions at least at the end of sq3 (script bug!) + // same happens very often in lsl5, sierra sci didnt fix it but it looked awful warning("fixing too large window, given left&right was %d, %d", dims.left, dims.right); r.left = 0; r.right = _screen->getWidth() - 1; @@ -496,6 +520,11 @@ void GfxPorts::priorityBandsInit(int16 bandCount, int16 top, int16 bottom) { // We fill space that is left over with the highest band (hardcoded 200 limit, because this algo isnt meant to be used on hires) for (y = _priorityBottom; y < 200; y++) _priorityBands[y] = _priorityBandCount; + + // adjust, if bottom is 200 (one over the actual screen range) - we could otherwise go possible out of bounds + // sierra sci also adjust accordingly + if (_priorityBottom == 200) + _priorityBottom--; } void GfxPorts::priorityBandsInit(byte *data) { diff --git a/engines/sci/graphics/ports.h b/engines/sci/graphics/ports.h index c8ce6b3470..818f92f44f 100644 --- a/engines/sci/graphics/ports.h +++ b/engines/sci/graphics/ports.h @@ -45,7 +45,7 @@ public: GfxPorts(SegManager *segMan, GfxScreen *screen); ~GfxPorts(); - void init(bool usesOldGfxFunctions, SciGui *gui, GfxPaint16 *paint16, GfxText16 *text16); + void init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *text16); void kernelSetActive(uint16 portId); Common::Rect kernelGetPicWindow(int16 &picTop, int16 &picLeft); @@ -102,7 +102,6 @@ private: typedef Common::List<Port *> PortList; SegManager *_segMan; - SciGui *_gui; GfxPaint16 *_paint16; GfxScreen *_screen; GfxText16 *_text16; diff --git a/engines/sci/graphics/robot.cpp b/engines/sci/graphics/robot.cpp index 2f711eb58a..d926e037f4 100644 --- a/engines/sci/graphics/robot.cpp +++ b/engines/sci/graphics/robot.cpp @@ -31,17 +31,17 @@ namespace Sci { #ifdef ENABLE_SCI32 -Robot::Robot(ResourceManager *resMan, GfxScreen *screen, GuiResourceId resourceId) +GfxRobot::GfxRobot(ResourceManager *resMan, GfxScreen *screen, GuiResourceId resourceId) : _resMan(resMan), _screen(screen), _resourceId(resourceId) { assert(resourceId != -1); initData(resourceId); } -Robot::~Robot() { +GfxRobot::~GfxRobot() { _resMan->unlockResource(_resource); } -void Robot::initData(GuiResourceId resourceId) { +void GfxRobot::initData(GuiResourceId resourceId) { _resource = _resMan->findResource(ResourceId(kResourceTypeRobot, resourceId), true); if (!_resource) { error("robot resource %d not found", resourceId); @@ -158,7 +158,7 @@ void Robot::initData(GuiResourceId resourceId) { // TODO: just trying around in here... -void Robot::draw() { +void GfxRobot::draw() { byte *bitmapData = _resourceData + ROBOT_FILE_STARTOFDATA; int x, y; //int frame; diff --git a/engines/sci/graphics/robot.h b/engines/sci/graphics/robot.h index 009b76a91c..80dae95f95 100644 --- a/engines/sci/graphics/robot.h +++ b/engines/sci/graphics/robot.h @@ -31,10 +31,10 @@ namespace Sci { #define ROBOT_FILE_STARTOFDATA 58 #ifdef ENABLE_SCI32 -class Robot { +class GfxRobot { public: - Robot(ResourceManager *resMan, GfxScreen *screen, GuiResourceId resourceId); - ~Robot(); + GfxRobot(ResourceManager *resMan, GfxScreen *screen, GuiResourceId resourceId); + ~GfxRobot(); void draw(); diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 0e054d5a76..488bb83ab3 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -35,8 +35,35 @@ namespace Sci { -GfxScreen::GfxScreen(ResourceManager *resMan, int16 width, int16 height, int upscaledHires) : - _resMan(resMan), _width(width), _height(height), _upscaledHires(upscaledHires) { +GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { + + // Scale the screen, if needed + _upscaledHires = GFX_SCREEN_UPSCALED_DISABLED; + + // King's Quest 6 and Gabriel Knight 1 have hires content, gk1/cd was able + // to provide that under DOS as well, but as gk1/floppy does support + // upscaled hires scriptswise, but doesn't actually have the hires content + // we need to limit it to platform windows. + if (g_sci->getPlatform() == Common::kPlatformWindows) { + if (g_sci->getGameId() == GID_KQ6) + _upscaledHires = GFX_SCREEN_UPSCALED_640x440; +#ifdef ENABLE_SCI32 + if (g_sci->getGameId() == GID_GK1) + _upscaledHires = GFX_SCREEN_UPSCALED_640x480; +#endif + } + + if (_resMan->detectHires()) { + _width = 640; + _height = 480; + } else { + _width = 320; + _height = 200; + } + + // Japanese versions of games use hi-res font on upscaled version of the game. + if ((g_sci->getLanguage() == Common::JA_JPN) && (getSciVersion() <= SCI_VERSION_1_1)) + _upscaledHires = GFX_SCREEN_UPSCALED_640x400; _pixels = _width * _height; @@ -80,8 +107,9 @@ GfxScreen::GfxScreen(ResourceManager *resMan, int16 width, int16 height, int ups _unditherState = true; if (_resMan->isVGA() || (_resMan->isAmiga32color())) { - // It's not 100% accurate to set white to be 255 for amiga 32-color games - // 255 is defined as white in our sci at all times, so it doesnt matter + // It is not 100% accurate to set white to be 255 for Amiga 32-color + // games. But 255 is defined as white in our SCI at all times, so it + // doesn't matter. _colorWhite = 255; if (getSciVersion() >= SCI_VERSION_1_1) _colorDefaultVectorData = 255; @@ -97,9 +125,9 @@ GfxScreen::GfxScreen(ResourceManager *resMan, int16 width, int16 height, int ups if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1) { // For SCI1.1 Mac, we need to expand the screen to accommodate for // the icon bar. Of course, both KQ6 and QFG1 VGA differ in size. - if (!scumm_stricmp(g_sci->getGameID(), "kq6")) + if (g_sci->getGameId() == GID_KQ6) initGraphics(_displayWidth, _displayHeight + 26, _displayWidth > 320); - else if (!scumm_stricmp(g_sci->getGameID(), "qfg1")) + else if (g_sci->getGameId() == GID_QFG1) initGraphics(_displayWidth, _displayHeight + 20, _displayWidth > 320); else error("Unknown SCI1.1 Mac game"); @@ -141,7 +169,10 @@ void GfxScreen::copyRectToScreen(const Common::Rect &rect) { } } -// This copies a rect to screen w/o scaling adjustment and is only meant to be used on hires graphics used in upscaled hires mode +/** + * This copies a rect to screen w/o scaling adjustment and is only meant to be + * used on hires graphics used in upscaled hires mode. + */ void GfxScreen::copyDisplayRectToScreen(const Common::Rect &rect) { if (!_upscaledHires) error("copyDisplayRectToScreen: not in upscaled hires mode"); @@ -192,15 +223,42 @@ void GfxScreen::putPixel(int x, int y, byte drawMask, byte color, byte priority, _controlScreen[offset] = control; } -// This will just change a pixel directly on displayscreen. Its supposed to get only used on upscaled-Hires games where -// hires content needs to get drawn ONTO the upscaled display screen (like japanese fonts, hires portraits, etc.) +/** + * This is used to put font pixels onto the screen - we adjust differently, so that we won't + * do triple pixel lines in any case on upscaled hires. That way the font will not get distorted + * Sierra SCI didn't do this + */ +void GfxScreen::putFontPixel(int startingY, int x, int y, byte color) { + int offset = (startingY + y) * _width + x; + + _visualScreen[offset] = color; + if (!_upscaledHires) { + _displayScreen[offset] = color; + } else { + int displayOffset = (_upscaledMapping[startingY] + y * 2) * _displayWidth + x * 2; + _displayScreen[displayOffset] = color; + _displayScreen[displayOffset + 1] = color; + displayOffset += _displayWidth; + _displayScreen[displayOffset] = color; + _displayScreen[displayOffset + 1] = color; + } +} + +/** + * This will just change a pixel directly on displayscreen. It is supposed to be + * only used on upscaled-Hires games where hires content needs to get drawn ONTO + * the upscaled display screen (like japanese fonts, hires portraits, etc.). + */ void GfxScreen::putPixelOnDisplay(int x, int y, byte color) { int offset = y * _displayWidth + x; _displayScreen[offset] = color; } -// Sierra's Bresenham line drawing -// WARNING: Do not just blindly replace this with Graphics::drawLine(), as it seems to create issues with flood fill +/** + * Sierra's Bresenham line drawing. + * WARNING: Do not replace this with Graphics::drawLine(), as this causes issues + * with flood fill, due to small difference in the Bresenham logic. + */ void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control) { int16 left = startPoint.x; int16 top = startPoint.y; @@ -263,7 +321,8 @@ void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte } } -// We put hires kanji chars onto upscaled background, so we need to adjust coordinates. Caller gives use low-res ones +// We put hires kanji chars onto upscaled background, so we need to adjust +// coordinates. Caller gives use low-res ones. void GfxScreen::putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, uint16 chr, byte color) { byte *displayPtr = _displayScreen + y * _displayWidth * 2 + x * 2; // we don't use outline, so color 0 is actually not used @@ -400,6 +459,11 @@ void GfxScreen::bitsRestore(byte *memoryPtr) { if (!_upscaledHires) error("bitsRestore() called w/o being in upscaled hires mode"); bitsRestoreScreen(rect, memoryPtr, _displayScreen, _displayWidth); + // WORKAROUND - we are not sure what sierra is doing. If we don't do this here, portraits won't get fully removed + // from screen. Some lowres showBits() call is used for that and it's not covering the whole area + // We would need to find out inside the kq6 windows interpreter, but this here works already and seems not to have + // any side-effects. The whole hires is hacked into the interpreter, so maybe this is even right. + copyDisplayRectToScreen(rect); } } @@ -435,7 +499,19 @@ void GfxScreen::bitsRestoreDisplayScreen(Common::Rect rect, byte *&memoryPtr) { } } -void GfxScreen::setPalette(Palette*pal) { +void GfxScreen::getPalette(Palette *pal) { + // just copy palette to system + byte bpal[4 * 256]; + // Get current palette, update it and put back + g_system->grabPalette(bpal, 0, 256); + for (int16 i = 1; i < 255; i++) { + pal->colors[i].r = bpal[i * 4]; + pal->colors[i].g = bpal[i * 4 + 1]; + pal->colors[i].b = bpal[i * 4 + 2]; + } +} + +void GfxScreen::setPalette(Palette *pal) { // just copy palette to system byte bpal[4 * 256]; // Get current palette, update it and put back @@ -557,19 +633,20 @@ void GfxScreen::debugShowMap(int mapNo) { copyToScreen(); } -void GfxScreen::scale2x(byte *src, byte *dst, int16 srcWidth, int16 srcHeight) { - int newWidth = srcWidth * 2; - byte *srcPtr = src; +void GfxScreen::scale2x(const byte *src, byte *dst, int16 srcWidth, int16 srcHeight) { + const int newWidth = srcWidth * 2; + const byte *srcPtr = src; for (int y = 0; y < srcHeight; y++) { for (int x = 0; x < srcWidth; x++) { - int destOffset = y * 2 * newWidth + x * 2; - dst[destOffset] = *srcPtr; - dst[destOffset + 1] = *srcPtr; - dst[destOffset + newWidth] = *srcPtr; - dst[destOffset + newWidth + 1] = *srcPtr; - srcPtr++; + const byte color = *srcPtr++; + dst[0] = color; + dst[1] = color; + dst[newWidth] = color; + dst[newWidth + 1] = color; + dst += 2; } + dst += newWidth; } } @@ -578,6 +655,24 @@ void GfxScreen::adjustToUpscaledCoordinates(int16 &y, int16 &x) { y = _upscaledMapping[y]; } +void GfxScreen::adjustBackUpscaledCoordinates(int16 &y, int16 &x) { + switch (_upscaledHires) { + case GFX_SCREEN_UPSCALED_640x400: + x /= 2; + y /= 2; + break; + case GFX_SCREEN_UPSCALED_640x440: + x /= 2; + y = (y * 5) / 11; + break; + case GFX_SCREEN_UPSCALED_640x480: + x /= 2; + y = (y * 5) / 12; + default: + break; + } +} + int16 GfxScreen::kernelPicNotValid(int16 newPicNotValid) { int16 oldPicNotValid; diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h index b2479e9735..f1e3d028a8 100644 --- a/engines/sci/graphics/screen.h +++ b/engines/sci/graphics/screen.h @@ -50,16 +50,21 @@ enum GfxScreenMasks { GFX_SCREEN_MASK_ALL = GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY|GFX_SCREEN_MASK_CONTROL }; -#define SCI_SCREEN_UNDITHERMEMORIAL_SIZE 256 +enum { + SCI_SCREEN_UNDITHERMEMORIAL_SIZE = 256 +}; /** - * Screen class, actually creates 3 (4) screens internally - which is visual/display (for the user), - * priority (contains priority information) and control (contains control information). Handles all operations to it - * and copies parts of visual/display screen to the actual screen, so the user can really see it. + * Screen class, actually creates 3 (4) screens internally: + * - visual/display (for the user), + * - priority (contains priority information) and + * - control (contains control information). + * Handles all operations to it and copies parts of visual/display screen to + * the actual screen, so the user can really see it. */ class GfxScreen { public: - GfxScreen(ResourceManager *resMan, int16 width = 320, int16 height = 200, int upscaledHires = GFX_SCREEN_UPSCALED_DISABLED); + GfxScreen(ResourceManager *resMan); ~GfxScreen(); uint16 getWidth() { return _width; } @@ -78,15 +83,16 @@ public: byte getDrawingMask(byte color, byte prio, byte control); void putPixel(int x, int y, byte drawMask, byte color, byte prio, byte control); + void putFontPixel(int startingY, int x, int y, byte color); void putPixelOnDisplay(int x, int y, byte color); void drawLine(Common::Point startPoint, Common::Point endPoint, byte color, byte prio, byte control); void drawLine(int16 left, int16 top, int16 right, int16 bottom, byte color, byte prio, byte control) { drawLine(Common::Point(left, top), Common::Point(right, bottom), color, prio, control); } - int getUpscaledHires() { + int getUpscaledHires() const { return _upscaledHires; } - bool getUnditherState() { + bool getUnditherState() const { return _unditherState; } void putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, uint16 chr, byte color); @@ -100,13 +106,15 @@ public: void bitsGetRect(byte *memoryPtr, Common::Rect *destRect); void bitsRestore(byte *memoryPtr); - void setPalette(Palette*pal); + void getPalette(Palette *pal); + void setPalette(Palette *pal); void setVerticalShakePos(uint16 shakePos); - void scale2x(byte *src, byte *dst, int16 srcWidth, int16 srcHeight); + void scale2x(const byte *src, byte *dst, int16 srcWidth, int16 srcHeight); void adjustToUpscaledCoordinates(int16 &y, int16 &x); + void adjustBackUpscaledCoordinates(int16 &y, int16 &x); void dither(bool addToFlag); void debugUnditherSetState(bool flag); @@ -138,27 +146,34 @@ private: bool _unditherState; int16 _unditherMemorial[SCI_SCREEN_UNDITHERMEMORIAL_SIZE]; - // these screens have the real resolution of the game engine (320x200 for SCI0/SCI1/SCI11 games, 640x480 for SCI2 games) - // SCI0 games will be dithered in here at any time + // These screens have the real resolution of the game engine (320x200 for + // SCI0/SCI1/SCI11 games, 640x480 for SCI2 games). SCI0 games will be + // dithered in here at any time. byte *_visualScreen; byte *_priorityScreen; byte *_controlScreen; - // this screen is the one that is actually displayed to the user. It may be 640x400 for japanese SCI1 games - // SCI0 games may be undithered in here. Only read from this buffer for Save/ShowBits usage. + // This screen is the one that is actually displayed to the user. It may be + // 640x400 for japanese SCI1 games. SCI0 games may be undithered in here. + // Only read from this buffer for Save/ShowBits usage. byte *_displayScreen; Common::Rect getScaledRect(Common::Rect rect); ResourceManager *_resMan; - // this is a pointer to the currently active screen (changing it only required for debug purposes) + /** + * Pointer to the currently active screen (changing it only required for + * debug purposes). + */ byte *_activeScreen; - // this variable defines, if upscaled hires is active and what upscaled mode is used + // This variable defines, if upscaled hires is active and what upscaled mode + // is used. int _upscaledHires; - // this here holds a translation for vertical coordinates between native (visual) and actual (display) screen + // This here holds a translation for vertical coordinates between native + // (visual) and actual (display) screen. int _upscaledMapping[SCI_SCREEN_UPSCALEDMAXHEIGHT + 1]; }; diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp index 952d13fbbd..4aa2346aed 100644 --- a/engines/sci/graphics/text16.cpp +++ b/engines/sci/graphics/text16.cpp @@ -73,28 +73,6 @@ void GfxText16::SetFont(GuiResourceId fontId) { _ports->_curPort->fontHeight = _font->getHeight(); } -void GfxText16::CodeSetFonts(int argc, reg_t *argv) { - int i; - - delete _codeFonts; - _codeFontsCount = argc; - _codeFonts = new GuiResourceId[argc]; - for (i = 0; i < argc; i++) { - _codeFonts[i] = (GuiResourceId)argv[i].toUint16(); - } -} - -void GfxText16::CodeSetColors(int argc, reg_t *argv) { - int i; - - delete _codeColors; - _codeColorsCount = argc; - _codeColors = new uint16[argc]; - for (i = 0; i < argc; i++) { - _codeColors[i] = argv[i].toUint16(); - } -} - void GfxText16::ClearChar(int16 chr) { if (_ports->_curPort->penMode != 1) return; @@ -106,10 +84,10 @@ void GfxText16::ClearChar(int16 chr) { _paint16->eraseRect(rect); } -// This internal function gets called as soon as a '|' is found in a text -// It will process the encountered code and set new font/set color -// We only support one-digit codes currently, don't know if multi-digit codes are possible -// Returns textcode character count +// This internal function gets called as soon as a '|' is found in a text. It +// will process the encountered code and set new font/set color. We only support +// one-digit codes currently, don't know if multi-digit codes are possible. +// Returns textcode character count. int16 GfxText16::CodeProcessing(const char *&text, GuiResourceId orgFontId, int16 orgPenColor) { const char *textCode = text; int16 textCodeSize = 0; @@ -155,9 +133,11 @@ int16 GfxText16::CodeProcessing(const char *&text, GuiResourceId orgFontId, int1 static const uint16 text16_punctuationSjis[] = { 0x9F82, 0xA182, 0xA382, 0xA582, 0xA782, 0xC182, 0xA782, 0xC182, 0xE182, 0xE382, 0xE582, 0xEC82, 0x4083, 0x4283, 0x4483, 0x4683, 0x4883, 0x6283, 0x8383, 0x8583, 0x8783, 0x8E83, 0x9583, 0x9683, - 0x5B81, 0x4181, 0x4281, 0x7681, 0x7881, 0x4981, 0x4881, 0 }; + 0x5B81, 0x4181, 0x4281, 0x7681, 0x7881, 0x4981, 0x4881, 0 +}; -// return max # of chars to fit maxwidth with full words, does not include breaking space +// return max # of chars to fit maxwidth with full words, does not include +// breaking space int16 GfxText16::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgFontId) { uint16 curChar = 0; int16 maxChars = 0, curCharCount = 0; @@ -217,9 +197,10 @@ int16 GfxText16::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgF uint16 nextChar; - // we remove the last char only, if maxWidth was actually equal width before adding the last char - // otherwise we won't get the same cutting as in sierra pc98 sci - // note: changing the while() instead will NOT WORK. it would break all sorts of regular sci games + // We remove the last char only, if maxWidth was actually equal width + // before adding the last char. Otherwise we won't get the same cutting + // as in sierra pc98 sci. Note: changing the while() instead will NOT + // WORK. it would break all sorts of regular sci games. if (maxWidth == (width - _font->getCharWidth(curChar))) { maxChars--; if (curChar > 0xFF) @@ -453,11 +434,14 @@ void GfxText16::Box(const char *text, int16 bshow, const Common::Rect &rect, Tex _ports->penColor(orgPenColor); if (doubleByteMode) { - // kanji is written by pc98 rom to screen directly. Because of GetLongest() behaviour (not cutting off the last - // char, that causes a new line), results in the script thinking that the text would need less space. The coordinate - // adjustment in fontsjis.cpp handles the incorrect centering because of that and this code actually shows all of - // the chars - if we don't do this, the scripts will only show most of the chars, but the last few pixels won't get - // shown most of the time. + // Kanji is written by pc98 rom to screen directly. Because of + // GetLongest() behaviour (not cutting off the last char, that causes a + // new line), results in the script thinking that the text would need + // less space. The coordinate adjustment in fontsjis.cpp handles the + // incorrect centering because of that and this code actually shows all + // of the chars - if we don't do this, the scripts will only show most + // of the chars, but the last few pixels won't get shown most of the + // time. Common::Rect kanjiRect = rect; _ports->offsetRect(kanjiRect); kanjiRect.left &= 0xFFC; @@ -478,7 +462,8 @@ void GfxText16::Draw_String(const char *text) { _ports->penColor(orgPenColor); } -// Sierra did this in their PC98 interpreter only, they identify a text as being sjis and then switch to font 900 +// Sierra did this in their PC98 interpreter only, they identify a text as being +// sjis and then switch to font 900 bool GfxText16::SwitchToFont900OnSjis(const char *text) { byte firstChar = (*(const byte *)text++); if (((firstChar >= 0x81) && (firstChar <= 0x9F)) || ((firstChar >= 0xE0) && (firstChar <= 0xEF))) { @@ -488,4 +473,35 @@ bool GfxText16::SwitchToFont900OnSjis(const char *text) { return false; } +void GfxText16::kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight) { + Common::Rect rect(0, 0, 0, 0); + Size(rect, text, font, maxWidth); + *textWidth = rect.width(); + *textHeight = rect.height(); +} + +// Used SCI1+ for text codes +void GfxText16::kernelTextFonts(int argc, reg_t *argv) { + int i; + + delete _codeFonts; + _codeFontsCount = argc; + _codeFonts = new GuiResourceId[argc]; + for (i = 0; i < argc; i++) { + _codeFonts[i] = (GuiResourceId)argv[i].toUint16(); + } +} + +// Used SCI1+ for text codes +void GfxText16::kernelTextColors(int argc, reg_t *argv) { + int i; + + delete _codeColors; + _codeColorsCount = argc; + _codeColors = new uint16[argc]; + for (i = 0; i < argc; i++) { + _codeColors[i] = argv[i].toUint16(); + } +} + } // End of namespace Sci diff --git a/engines/sci/graphics/text16.h b/engines/sci/graphics/text16.h index 2885fc928b..71b602d116 100644 --- a/engines/sci/graphics/text16.h +++ b/engines/sci/graphics/text16.h @@ -48,8 +48,6 @@ public: GfxFont *GetFont(); void SetFont(GuiResourceId fontId); - void CodeSetFonts(int argc, reg_t *argv); - void CodeSetColors(int argc, reg_t *argv); int16 CodeProcessing(const char *&text, GuiResourceId orgFontId, int16 orgPenColor); void ClearChar(int16 chr); @@ -67,6 +65,10 @@ public: GfxFont *_font; + void kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight); + void kernelTextFonts(int argc, reg_t *argv); + void kernelTextColors(int argc, reg_t *argv); + private: void init(); bool SwitchToFont900OnSjis(const char *text); diff --git a/engines/sci/graphics/transitions.cpp b/engines/sci/graphics/transitions.cpp index 1976326aa9..c1f626449f 100644 --- a/engines/sci/graphics/transitions.cpp +++ b/engines/sci/graphics/transitions.cpp @@ -31,15 +31,14 @@ #include "sci/sci.h" #include "sci/engine/state.h" -#include "sci/graphics/gui.h" #include "sci/graphics/screen.h" #include "sci/graphics/palette.h" #include "sci/graphics/transitions.h" namespace Sci { -GfxTransitions::GfxTransitions(SciGui *gui, GfxScreen *screen, GfxPalette *palette, bool isVGA) - : _gui(gui), _screen(screen), _palette(palette), _isVGA(isVGA) { +GfxTransitions::GfxTransitions(GfxScreen *screen, GfxPalette *palette, bool isVGA) + : _screen(screen), _palette(palette), _isVGA(isVGA) { init(); } @@ -159,7 +158,8 @@ void GfxTransitions::doit(Common::Rect picRect) { } if (_blackoutFlag) { - // We need to find out what transition we are supposed to use for blackout + // We need to find out what transition we are supposed to use for + // blackout translationEntry = translateNumber(_number, blackoutTransitionIDs); if (translationEntry) { doTransition(translationEntry->newId, true); @@ -168,12 +168,15 @@ void GfxTransitions::doit(Common::Rect picRect) { } } + _palette->palVaryPrepareForTransition(); + // Now we do the actual transition to the new screen doTransition(_number, false); if (picRect.bottom != _screen->getHeight()) { // TODO: this is a workaround for lsl6 not showing menubar when playing - // There is some new code in the sierra sci in ShowPic that seems to do something similar to this + // There is some new code in the sierra sci in ShowPic that seems to do + // something similar to this _screen->copyToScreen(); g_system->updateScreen(); } @@ -181,8 +184,8 @@ void GfxTransitions::doit(Common::Rect picRect) { _screen->_picNotValid = 0; } -// This may get called twice, if blackoutFlag is set. It will get once called with blackoutFlag set and another time -// with no blackoutFlag. +// This may get called twice, if blackoutFlag is set. It will get once called +// with blackoutFlag set and another time with no blackoutFlag. void GfxTransitions::doTransition(int16 number, bool blackoutFlag) { if (number != SCI_TRANSITIONS_FADEPALETTE) { setNewPalette(blackoutFlag); @@ -193,7 +196,7 @@ void GfxTransitions::doTransition(int16 number, bool blackoutFlag) { verticalRollFromCenter(blackoutFlag); break; case SCI_TRANSITIONS_VERTICALROLL_TOCENTER: - verticalRollFromCenter(blackoutFlag); + verticalRollToCenter(blackoutFlag); break; case SCI_TRANSITIONS_HORIZONTALROLL_FROMCENTER: horizontalRollFromCenter(blackoutFlag); @@ -277,7 +280,8 @@ void GfxTransitions::copyRectToScreen(const Common::Rect rect, bool blackoutFlag } } -// Note: dont do too many steps in here, otherwise cpu will crap out because of the load +// Note: don't do too many steps in here, otherwise cpu will crap out because of +// the load void GfxTransitions::fadeOut() { byte oldPalette[4 * 256], workPalette[4 * 256]; int16 stepNr, colorNr; @@ -291,23 +295,24 @@ void GfxTransitions::fadeOut() { workPalette[colorNr * 4 + 2] = oldPalette[colorNr * 4 + 2] * stepNr / 100; } g_system->setPalette(workPalette + 4, 1, 254); - _gui->wait(2); + g_sci->getEngineState()->wait(2); } } -// Note: dont do too many steps in here, otherwise cpu will crap out because of the load +// Note: don't do too many steps in here, otherwise cpu will crap out because of +// the load void GfxTransitions::fadeIn() { int16 stepNr; for (stepNr = 0; stepNr <= 100; stepNr += 10) { _palette->kernelSetIntensity(1, 255, stepNr, true); - _gui->wait(2); + g_sci->getEngineState()->wait(2); } } -// pixelates the new picture over the old one - works against the whole screen +// Pixelates the new picture over the old one - works against the whole screen. // TODO: it seems this needs to get applied on _picRect only if possible -void GfxTransitions::pixelation (bool blackoutFlag) { +void GfxTransitions::pixelation(bool blackoutFlag) { uint16 mask = 0x40, stepNr = 0; Common::Rect pixelRect; @@ -327,7 +332,7 @@ void GfxTransitions::pixelation (bool blackoutFlag) { } while (mask != 0x40); } -// like pixelation but uses 8x8 blocks - works against the whole screen +// Like pixelation but uses 8x8 blocks - works against the whole screen. // TODO: it seems this needs to get applied on _picRect only if possible void GfxTransitions::blocks(bool blackoutFlag) { uint16 mask = 0x40, stepNr = 0; @@ -349,7 +354,8 @@ void GfxTransitions::blocks(bool blackoutFlag) { } while (mask != 0x40); } -// directly shows new screen starting up/down/left/right and going to the opposite direction - works on _picRect area only +// Directly shows new screen starting up/down/left/right and going to the +// opposite direction - works on _picRect area only void GfxTransitions::straight(int16 number, bool blackoutFlag) { int16 stepNr = 0; Common::Rect newScreenRect = _picRect; @@ -401,7 +407,8 @@ void GfxTransitions::straight(int16 number, bool blackoutFlag) { } } -// scroll old screen (up/down/left/right) and insert new screen that way - works on _picRect area only +// Scroll old screen (up/down/left/right) and insert new screen that way - works +// on _picRect area only. void GfxTransitions::scroll(int16 number) { int16 screenWidth, screenHeight; byte *oldScreenPtr; @@ -440,8 +447,12 @@ void GfxTransitions::scroll(int16 number) { } stepNr++; } - if ((stepNr & 1) == 0) - g_system->updateScreen(); + if ((stepNr & 1) == 0) { + if (g_system->getMillis() - g_sci->getEngineState()->_screenUpdateTime >= 1000 / 60) { + g_system->updateScreen(); + g_sci->getEngineState()->_screenUpdateTime = g_system->getMillis(); + } + } break; case SCI_TRANSITIONS_SCROLL_RIGHT: @@ -461,8 +472,12 @@ void GfxTransitions::scroll(int16 number) { } stepNr++; } - if ((stepNr & 1) == 0) - g_system->updateScreen(); + if ((stepNr & 1) == 0) { + if (g_system->getMillis() - g_sci->getEngineState()->_screenUpdateTime >= 1000 / 60) { + g_system->updateScreen(); + g_sci->getEngineState()->_screenUpdateTime = g_system->getMillis(); + } + } break; case SCI_TRANSITIONS_SCROLL_UP: @@ -503,7 +518,8 @@ void GfxTransitions::scroll(int16 number) { } } -// vertically displays new screen starting from center - works on _picRect area only +// Vertically displays new screen starting from center - works on _picRect area +// only void GfxTransitions::verticalRollFromCenter(bool blackoutFlag) { Common::Rect leftRect = Common::Rect(_picRect.left + (_picRect.width() / 2) -1, _picRect.top, _picRect.left + (_picRect.width() / 2), _picRect.bottom); Common::Rect rightRect = Common::Rect(leftRect.right, _picRect.top, leftRect.right + 1, _picRect.bottom); @@ -519,7 +535,8 @@ void GfxTransitions::verticalRollFromCenter(bool blackoutFlag) { } } -// vertically displays new screen starting from edges - works on _picRect area only +// Vertically displays new screen starting from edges - works on _picRect area +// only void GfxTransitions::verticalRollToCenter(bool blackoutFlag) { Common::Rect leftRect = Common::Rect(_picRect.left, _picRect.top, _picRect.left + 1, _picRect.bottom); Common::Rect rightRect = Common::Rect(leftRect.right - 1, _picRect.top, leftRect.right, _picRect.bottom); @@ -531,7 +548,8 @@ void GfxTransitions::verticalRollToCenter(bool blackoutFlag) { } } -// horizontally displays new screen starting from center - works on _picRect area only +// Horizontally displays new screen starting from center - works on _picRect +// area only void GfxTransitions::horizontalRollFromCenter(bool blackoutFlag) { Common::Rect upperRect = Common::Rect(_picRect.left, _picRect.top + (_picRect.height() / 2) - 1, _picRect.right, _picRect.top + (_picRect.height() / 2)); Common::Rect lowerRect = Common::Rect(upperRect.left, upperRect.bottom, upperRect.right, upperRect.bottom + 1); @@ -547,7 +565,8 @@ void GfxTransitions::horizontalRollFromCenter(bool blackoutFlag) { } } -// horizontally displays new screen starting from upper and lower edge - works on _picRect area only +// Horizontally displays new screen starting from upper and lower edge - works +// on _picRect area only void GfxTransitions::horizontalRollToCenter(bool blackoutFlag) { Common::Rect upperRect = Common::Rect(_picRect.left, _picRect.top, _picRect.right, _picRect.top + 1); Common::Rect lowerRect = Common::Rect(upperRect.left, _picRect.bottom - 1, upperRect.right, _picRect.bottom); @@ -559,8 +578,8 @@ void GfxTransitions::horizontalRollToCenter(bool blackoutFlag) { } } -// diagonally displays new screen starting from center - works on _picRect area only -// assumes that height of rect is larger than width +// Diagonally displays new screen starting from center - works on _picRect area +// only. Assumes that height of rect is larger than width. void GfxTransitions::diagonalRollFromCenter(bool blackoutFlag) { int16 halfHeight = _picRect.height() / 2; Common::Rect upperRect(_picRect.left + halfHeight - 2, _picRect.top + halfHeight, _picRect.right - halfHeight + 1, _picRect.top + halfHeight + 1); @@ -589,8 +608,8 @@ void GfxTransitions::diagonalRollFromCenter(bool blackoutFlag) { } } -// diagonally displays new screen starting from edges - works on _picRect area only -// assumes that height of rect is larger than width +// Diagonally displays new screen starting from edges - works on _picRect area +// only. Assumes that height of rect is larger than width. void GfxTransitions::diagonalRollToCenter(bool blackoutFlag) { Common::Rect upperRect(_picRect.left, _picRect.top, _picRect.right, _picRect.top + 1); Common::Rect lowerRect(_picRect.left, _picRect.bottom - 1, _picRect.right, _picRect.bottom); diff --git a/engines/sci/graphics/transitions.h b/engines/sci/graphics/transitions.h index 9a1a412d5b..788cefabca 100644 --- a/engines/sci/graphics/transitions.h +++ b/engines/sci/graphics/transitions.h @@ -65,7 +65,7 @@ class Screen; */ class GfxTransitions { public: - GfxTransitions(SciGui *gui, GfxScreen *screen, GfxPalette *palette, bool isVGA); + GfxTransitions(GfxScreen *screen, GfxPalette *palette, bool isVGA); ~GfxTransitions(); void setup(int16 number, bool blackoutFlag); @@ -92,7 +92,6 @@ private: void diagonalRollToCenter(bool blackoutFlag); void updateScreenAndWait(int msec); - SciGui *_gui; GfxScreen *_screen; GfxPalette *_palette; diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 2ba14fbd8f..93df45820c 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -62,6 +62,7 @@ void GfxView::initData(GuiResourceId resourceId) { error("view resource %d not found", resourceId); } _resourceData = _resource->data; + _resourceSize = _resource->size; byte *celData, *loopData; uint16 celOffset; @@ -75,12 +76,28 @@ void GfxView::initData(GuiResourceId resourceId) { byte seekEntry; bool isEGA = false; bool isCompressed = true; + ViewType curViewType = _resMan->getViewType(); _loopCount = 0; _embeddedPal = false; _EGAmapping = NULL; + _isSci2Hires = false; + + // If we find an SCI1/SCI1.1 view (not amiga), we switch to that type for + // EGA. This could get used to make view patches for EGA games, where the + // new views include more colors. Users could manually adjust old views to + // make them look better (like removing dithered colors that aren't caught + // by our undithering or even improve the graphics overall). + if (curViewType == kViewEga) { + if (_resourceData[1] == 0x80) { + curViewType = kViewVga; + } else { + if (READ_LE_UINT16(_resourceData + 4) == 1) + curViewType = kViewVga11; + } + } - switch (_resMan->getViewType()) { + switch (curViewType) { case kViewEga: // View-format SCI0 (and Amiga 16 colors) isEGA = true; case kViewAmiga: // View-format Amiga (32 colors) @@ -95,19 +112,21 @@ void GfxView::initData(GuiResourceId resourceId) { palOffset = READ_LE_UINT16(_resourceData + 6); if (palOffset && palOffset != 0x100) { - // Some SCI0/SCI01 games also have an offset set. It seems that it points to a 16-byte mapping table - // but on those games using that mapping will actually screw things up. - // On the other side: vga sci1 games have this pointing to a VGA palette - // and ega sci1 games have this pointing to a 8x16 byte mapping table that needs to get applied then + // Some SCI0/SCI01 games also have an offset set. It seems that it + // points to a 16-byte mapping table but on those games using that + // mapping will actually screw things up. On the other side: VGA + // SCI1 games have this pointing to a VGA palette and EGA SCI1 games + // have this pointing to a 8x16 byte mapping table that needs to get + // applied then. if (!isEGA) { - _palette->createFromData(&_resourceData[palOffset], &_viewPalette); + _palette->createFromData(&_resourceData[palOffset], _resourceSize - palOffset, &_viewPalette); _embeddedPal = true; } else { // Only use the EGA-mapping, when being SCI1 if (getSciVersion() >= SCI_VERSION_1_EGA) { _EGAmapping = &_resourceData[palOffset]; for (EGAmapNr = 0; EGAmapNr < SCI_VIEW_EGAMAPPING_COUNT; EGAmapNr++) { - if (memcmp(_EGAmapping, EGAmappingStraight, SCI_VIEW_EGAMAPPING_SIZE)!=0) + if (memcmp(_EGAmapping, EGAmappingStraight, SCI_VIEW_EGAMAPPING_SIZE) != 0) break; _EGAmapping += SCI_VIEW_EGAMAPPING_SIZE; } @@ -169,12 +188,14 @@ void GfxView::initData(GuiResourceId resourceId) { case kViewVga11: // View-format SCI1.1+ // HeaderSize:WORD LoopCount:BYTE Unknown:BYTE Version:WORD Unknown:WORD PaletteOffset:WORD - headerSize = READ_SCI11ENDIAN_UINT16(_resourceData + 0) + 2; // headerSize is not part of the header, so its added + headerSize = READ_SCI11ENDIAN_UINT16(_resourceData + 0) + 2; // headerSize is not part of the header, so it's added assert(headerSize >= 16); _loopCount = _resourceData[2]; assert(_loopCount); + _isSci2Hires = _resourceData[5] == 1 ? true : false; palOffset = READ_SCI11ENDIAN_UINT32(_resourceData + 8); - // FIXME: After LoopCount there is another byte and its set for view 50 within Laura Bow 2 CD, check what it means + // FIXME: After LoopCount there is another byte and its set for view 50 + // within Laura Bow 2 CD, check what it means. loopData = _resourceData + headerSize; loopSize = _resourceData[12]; @@ -183,7 +204,7 @@ void GfxView::initData(GuiResourceId resourceId) { assert(celSize >= 32); if (palOffset) { - _palette->createFromData(&_resourceData[palOffset], &_viewPalette); + _palette->createFromData(&_resourceData[palOffset], _resourceSize - palOffset, &_viewPalette); _embeddedPal = true; } @@ -221,6 +242,9 @@ void GfxView::initData(GuiResourceId resourceId) { cel->offsetEGA = 0; cel->offsetRLE = READ_SCI11ENDIAN_UINT32(celData + 24); cel->offsetLiteral = READ_SCI11ENDIAN_UINT32(celData + 28); + // GK1-hires content is actually uncompressed, we need to swap both so that we process it as such + if ((cel->offsetRLE) && (!cel->offsetLiteral)) + SWAP(cel->offsetRLE, cel->offsetLiteral); cel->rawBitmap = 0; if (_loop[loopNo].mirrorFlag) @@ -236,65 +260,68 @@ void GfxView::initData(GuiResourceId resourceId) { } } -GuiResourceId GfxView::getResourceId() { +GuiResourceId GfxView::getResourceId() const { return _resourceId; } -int16 GfxView::getWidth(int16 loopNo, int16 celNo) { - loopNo = CLIP<int16>(loopNo, 0, _loopCount - 1); - celNo = CLIP<int16>(celNo, 0, _loop[loopNo].celCount - 1); - return _loopCount ? _loop[loopNo].cel[celNo].width : 0; +int16 GfxView::getWidth(int16 loopNo, int16 celNo) const { + return _loopCount ? getCelInfo(loopNo, celNo)->width : 0; } -int16 GfxView::getHeight(int16 loopNo, int16 celNo) { - loopNo = CLIP<int16>(loopNo, 0, _loopCount -1); - celNo = CLIP<int16>(celNo, 0, _loop[loopNo].celCount - 1); - return _loopCount ? _loop[loopNo].cel[celNo].height : 0; +int16 GfxView::getHeight(int16 loopNo, int16 celNo) const { + return _loopCount ? getCelInfo(loopNo, celNo)->height : 0; } -CelInfo *GfxView::getCelInfo(int16 loopNo, int16 celNo) { +const CelInfo *GfxView::getCelInfo(int16 loopNo, int16 celNo) const { + assert(_loopCount); loopNo = CLIP<int16>(loopNo, 0, _loopCount - 1); celNo = CLIP<int16>(celNo, 0, _loop[loopNo].celCount - 1); - return _loopCount ? &_loop[loopNo].cel[celNo] : NULL; + return &_loop[loopNo].cel[celNo]; } -LoopInfo *GfxView::getLoopInfo(int16 loopNo) { +uint16 GfxView::getCelCount(int16 loopNo) const { + assert(_loopCount); loopNo = CLIP<int16>(loopNo, 0, _loopCount - 1); - return _loopCount ? &_loop[loopNo] : NULL; + return _loop[loopNo].celCount; } -void GfxView::getCelRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, Common::Rect *outRect) { - CelInfo *celInfo = getCelInfo(loopNo, celNo); - if (celInfo) { - outRect->left = x + celInfo->displaceX - (celInfo->width >> 1); - outRect->right = outRect->left + celInfo->width; - outRect->bottom = y + celInfo->displaceY - z + 1; - outRect->top = outRect->bottom - celInfo->height; - } +Palette *GfxView::getPalette() { + return _embeddedPal ? &_viewPalette : NULL; +} + +bool GfxView::isSci2Hires() { + return _isSci2Hires; +} + +void GfxView::getCelRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, Common::Rect &outRect) const { + const CelInfo *celInfo = getCelInfo(loopNo, celNo); + outRect.left = x + celInfo->displaceX - (celInfo->width >> 1); + outRect.right = outRect.left + celInfo->width; + outRect.bottom = y + celInfo->displaceY - z + 1; + outRect.top = outRect.bottom - celInfo->height; } -void GfxView::getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, int16 scaleX, int16 scaleY, Common::Rect *outRect) { +void GfxView::getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, int16 scaleX, int16 scaleY, Common::Rect &outRect) const { int16 scaledDisplaceX, scaledDisplaceY; int16 scaledWidth, scaledHeight; - CelInfo *celInfo = getCelInfo(loopNo, celNo); - if (celInfo) { - // Scaling displaceX/Y, Width/Height - scaledDisplaceX = (celInfo->displaceX * scaleX) >> 7; - scaledDisplaceY = (celInfo->displaceY * scaleY) >> 7; - scaledWidth = (celInfo->width * scaleX) >> 7; - scaledHeight = (celInfo->height * scaleY) >> 7; - scaledWidth = CLIP<int16>(scaledWidth, 0, _screen->getWidth()); - scaledHeight = CLIP<int16>(scaledHeight, 0, _screen->getHeight()); - - outRect->left = x + scaledDisplaceX - (scaledWidth >> 1); - outRect->right = outRect->left + scaledWidth; - outRect->bottom = y + scaledDisplaceY - z + 1; - outRect->top = outRect->bottom - scaledHeight; - } + const CelInfo *celInfo = getCelInfo(loopNo, celNo); + + // Scaling displaceX/Y, Width/Height + scaledDisplaceX = (celInfo->displaceX * scaleX) >> 7; + scaledDisplaceY = (celInfo->displaceY * scaleY) >> 7; + scaledWidth = (celInfo->width * scaleX) >> 7; + scaledHeight = (celInfo->height * scaleY) >> 7; + scaledWidth = CLIP<int16>(scaledWidth, 0, _screen->getWidth()); + scaledHeight = CLIP<int16>(scaledHeight, 0, _screen->getHeight()); + + outRect.left = x + scaledDisplaceX - (scaledWidth >> 1); + outRect.right = outRect.left + scaledWidth; + outRect.bottom = y + scaledDisplaceY - z + 1; + outRect.top = outRect.bottom - scaledHeight; } void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCount) { - CelInfo *celInfo = getCelInfo(loopNo, celNo); + const CelInfo *celInfo = getCelInfo(loopNo, celNo); byte *rlePtr; byte *literalPtr; uint32 pixelNo = 0, runLength; @@ -309,78 +336,42 @@ void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCou memset(outPtr + pixelNo, pixel & 0x0F, MIN<uint32>(runLength, pixelCount - pixelNo)); pixelNo += runLength; } - return; - } - - rlePtr = _resourceData + celInfo->offsetRLE; - if (!celInfo->offsetLiteral) { // no additional literal data - if (_resMan->isAmiga32color()) { - // decompression for amiga views - while (pixelNo < pixelCount) { - pixel = *rlePtr++; - if (pixel & 0x07) { // fill with color - runLength = pixel & 0x07; - pixel = pixel >> 3; - while (runLength-- && pixelNo < pixelCount) { - outPtr[pixelNo++] = pixel; - } - } else { // fill with transparent - runLength = pixel >> 3; - pixelNo += runLength; - } - } - return; - } else { - // decompression for data that has just one combined stream - while (pixelNo < pixelCount) { - pixel = *rlePtr++; - runLength = pixel & 0x3F; - switch (pixel & 0xC0) { - case 0: // copy bytes as-is - while (runLength-- && pixelNo < pixelCount) - outPtr[pixelNo++] = *rlePtr++; - break; - case 0x80: // fill with color - memset(outPtr + pixelNo, *rlePtr++, MIN<uint32>(runLength, pixelCount - pixelNo)); - pixelNo += runLength; - break; - case 0xC0: // fill with transparent - pixelNo += runLength; - break; - } - } - return; - } } else { - literalPtr = _resourceData + celInfo->offsetLiteral; - if (celInfo->offsetRLE) { - if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1) { - // Crazy-Ass compression for SCI1.1+ Mac + // We fill the buffer with transparent pixels, so that we can later skip + // over pixels to automatically have them transparent + // Also some RLE compressed cels are possibly ending with the last + // non-transparent pixel (is this even possible with the current code?) + memset(outPtr, _loop[loopNo].cel[celNo].clearKey, pixelCount); + + rlePtr = _resourceData + celInfo->offsetRLE; + if (!celInfo->offsetLiteral) { // no additional literal data + if (_resMan->isAmiga32color()) { + // decompression for amiga views while (pixelNo < pixelCount) { - uint32 pixelLine = pixelNo; - runLength = *rlePtr++; - pixelNo += runLength; - runLength = *rlePtr++; - while (runLength-- && pixelNo < pixelCount) { - outPtr[pixelNo] = *literalPtr++; - if (outPtr[pixelNo] == 255) - outPtr[pixelNo] = 0; - pixelNo++; + pixel = *rlePtr++; + if (pixel & 0x07) { // fill with color + runLength = pixel & 0x07; + pixel = pixel >> 3; + while (runLength-- && pixelNo < pixelCount) { + outPtr[pixelNo++] = pixel; + } + } else { // fill with transparent + runLength = pixel >> 3; + pixelNo += runLength; } - pixelNo = pixelLine + celInfo->width; } } else { - // decompression for data that has separate rle and literal streams + // decompression for data that has just one combined stream while (pixelNo < pixelCount) { pixel = *rlePtr++; runLength = pixel & 0x3F; switch (pixel & 0xC0) { case 0: // copy bytes as-is while (runLength-- && pixelNo < pixelCount) - outPtr[pixelNo++] = *literalPtr++; + outPtr[pixelNo++] = *rlePtr++; break; case 0x80: // fill with color - memset(outPtr + pixelNo, *literalPtr++, MIN<uint32>(runLength, pixelCount - pixelNo)); + memset(outPtr + pixelNo, *rlePtr++, MIN<uint32>(runLength, pixelCount - pixelNo)); pixelNo += runLength; break; case 0xC0: // fill with transparent @@ -390,15 +381,53 @@ void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCou } } } else { - // literal stream only, so no compression - memcpy(outPtr, literalPtr, pixelCount); + literalPtr = _resourceData + celInfo->offsetLiteral; + if (celInfo->offsetRLE) { + if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1) { + // compression for SCI1.1+ Mac + while (pixelNo < pixelCount) { + uint32 pixelLine = pixelNo; + runLength = *rlePtr++; + pixelNo += runLength; + runLength = *rlePtr++; + while (runLength-- && pixelNo < pixelCount) { + outPtr[pixelNo] = *literalPtr++; + if (outPtr[pixelNo] == 255) + outPtr[pixelNo] = 0; + pixelNo++; + } + pixelNo = pixelLine + celInfo->width; + } + } else { + // decompression for data that has separate rle and literal streams + while (pixelNo < pixelCount) { + pixel = *rlePtr++; + runLength = pixel & 0x3F; + switch (pixel & 0xC0) { + case 0: // copy bytes as-is + while (runLength-- && pixelNo < pixelCount) + outPtr[pixelNo++] = *literalPtr++; + break; + case 0x80: // fill with color + memset(outPtr + pixelNo, *literalPtr++, MIN<uint32>(runLength, pixelCount - pixelNo)); + pixelNo += runLength; + break; + case 0xC0: // fill with transparent + pixelNo += runLength; + break; + } + } + } + } else { + // literal stream only, so no compression + memcpy(outPtr, literalPtr, pixelCount); + pixelNo = pixelCount; + } } - return; } - error("Unable to decompress view"); } -byte *GfxView::getBitmap(int16 loopNo, int16 celNo) { +const byte *GfxView::getBitmap(int16 loopNo, int16 celNo) { loopNo = CLIP<int16>(loopNo, 0, _loopCount -1); celNo = CLIP<int16>(celNo, 0, _loop[loopNo].celCount - 1); if (_loop[loopNo].cel[celNo].rawBitmap) @@ -411,9 +440,7 @@ byte *GfxView::getBitmap(int16 loopNo, int16 celNo) { _loop[loopNo].cel[celNo].rawBitmap = new byte[pixelCount]; byte *pBitmap = _loop[loopNo].cel[celNo].rawBitmap; - // Some RLE compressed cels end with the last non-transparent pixel, thats why we fill it up here - // FIXME: change this to fill the remaining bytes within unpackCel() - memset(pBitmap, _loop[loopNo].cel[celNo].clearKey, pixelCount); + // unpack the actual cel bitmap data unpackCel(loopNo, celNo, pBitmap, pixelCount); if (!_resMan->isVGA()) { @@ -429,17 +456,21 @@ byte *GfxView::getBitmap(int16 loopNo, int16 celNo) { return _loop[loopNo].cel[celNo].rawBitmap; } -// Called after unpacking an EGA cel, this will try to undither (parts) of the cel if the dithering in here -// matches dithering used by the current picture +/** + * Called after unpacking an EGA cel, this will try to undither (parts) of the + * cel if the dithering in here matches dithering used by the current picture. + */ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte clearKey) { int16 *unditherMemorial = _screen->unditherGetMemorial(); - // It makes no sense to go further, if no memorial data from current picture is available + // It makes no sense to go further, if no memorial data from current picture + // is available if (!unditherMemorial) return; // Makes no sense to process bitmaps that are 3 pixels wide or less - if (width <= 3) return; + if (width <= 3) + return; // If EGA mapping is used for this view, dont do undithering as well if (_EGAmapping) @@ -453,7 +484,8 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl memset(&bitmapMemorial, 0, sizeof(bitmapMemorial)); - // Count all seemingly dithered pixel-combinations as soon as at least 4 pixels are adjacent + // Count all seemingly dithered pixel-combinations as soon as at least 4 + // pixels are adjacent curPtr = bitmapPtr; for (y = 0; y < height; y++) { color1 = curPtr[0]; color2 = (curPtr[1] << 4) | curPtr[2]; @@ -466,17 +498,20 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl } } - // Now compare both memorial tables to find out matching dithering-combinations + // Now compare both memorial tables to find out matching + // dithering-combinations bool unditherTable[SCI_SCREEN_UNDITHERMEMORIAL_SIZE]; byte color, unditherCount = 0; memset(&unditherTable, false, sizeof(unditherTable)); for (color = 0; color < 255; color++) { if ((bitmapMemorial[color] > 5) && (unditherMemorial[color] > 200)) { - // match found, check if colorKey is contained -> if so, we ignore of course + // match found, check if colorKey is contained -> if so, we ignore + // of course color1 = color & 0x0F; color2 = color >> 4; if ((color1 != clearKey) && (color2 != clearKey) && (color1 != color2)) { // so set this and the reversed color-combination for undithering - unditherTable[color] = true; unditherTable[(color1 << 4) | color2] = true; + unditherTable[color] = true; + unditherTable[(color1 << 4) | color2] = true; unditherCount++; } } @@ -493,8 +528,9 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl for (x = 1; x < width; x++) { color = (color << 4) | curPtr[1]; if (unditherTable[color]) { - // some color with black? turn colors around otherwise it wont be the right color at all - if ((color & 0xF0)==0) + // Some color with black? Turn colors around, otherwise it won't + // be the right color at all. + if ((color & 0xF0) == 0) color = (color << 4) | (color >> 4); curPtr[0] = color; curPtr[1] = color; } @@ -504,15 +540,15 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl } } -void GfxView::draw(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRectTranslated, int16 loopNo, int16 celNo, byte priority, uint16 EGAmappingNr, bool upscaledHires) { - Palette *palette = _embeddedPal ? &_viewPalette : &_palette->_sysPalette; - CelInfo *celInfo = getCelInfo(loopNo, celNo); - byte *bitmap = getBitmap(loopNo, celNo); - int16 celHeight = celInfo->height, celWidth = celInfo->width; - int16 width, height; - byte clearKey = celInfo->clearKey; - byte color; - byte drawMask = priority == 255 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY; +void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const Common::Rect &clipRectTranslated, + int16 loopNo, int16 celNo, byte priority, uint16 EGAmappingNr, bool upscaledHires) { + const Palette *palette = _embeddedPal ? &_viewPalette : &_palette->_sysPalette; + const CelInfo *celInfo = getCelInfo(loopNo, celNo); + const byte *bitmap = getBitmap(loopNo, celNo); + const int16 celHeight = celInfo->height; + const int16 celWidth = celInfo->width; + const byte clearKey = celInfo->clearKey; + const byte drawMask = (priority == 255) ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY; int x, y; if (_embeddedPal) { @@ -520,24 +556,27 @@ void GfxView::draw(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRe _palette->set(&_viewPalette, false); } - width = MIN(clipRect.width(), celWidth); - height = MIN(clipRect.height(), celHeight); + const int16 width = MIN(clipRect.width(), celWidth); + const int16 height = MIN(clipRect.height(), celHeight); bitmap += (clipRect.top - rect.top) * celWidth + (clipRect.left - rect.left); if (!_EGAmapping) { for (y = 0; y < height; y++, bitmap += celWidth) { for (x = 0; x < width; x++) { - color = bitmap[x]; + const byte color = bitmap[x]; if (color != clearKey) { + const int x2 = clipRectTranslated.left + x; + const int y2 = clipRectTranslated.top + y; if (!upscaledHires) { - if (priority >= _screen->getPriority(clipRectTranslated.left + x, clipRectTranslated.top + y)) - _screen->putPixel(clipRectTranslated.left + x, clipRectTranslated.top + y, drawMask, palette->mapping[color], priority, 0); + if (priority >= _screen->getPriority(x2, y2)) + _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0); } else { - // UpscaledHires means view is hires and is supposed to get drawn onto lowres screen - // FIXME(?): we can't read priority directly with the hires coordinates. may not be needed at all - // in kq6 - _screen->putPixelOnDisplay(clipRectTranslated.left + x, clipRectTranslated.top + y, palette->mapping[color]); + // UpscaledHires means view is hires and is supposed to + // get drawn onto lowres screen. + // FIXME(?): we can't read priority directly with the + // hires coordinates. may not be needed at all in kq6 + _screen->putPixelOnDisplay(x2, y2, palette->mapping[color]); } } } @@ -546,30 +585,34 @@ void GfxView::draw(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRe byte *EGAmapping = _EGAmapping + (EGAmappingNr * SCI_VIEW_EGAMAPPING_SIZE); for (y = 0; y < height; y++, bitmap += celWidth) { for (x = 0; x < width; x++) { - color = EGAmapping[bitmap[x]]; - if (color != clearKey && priority >= _screen->getPriority(clipRectTranslated.left + x, clipRectTranslated.top + y)) - _screen->putPixel(clipRectTranslated.left + x, clipRectTranslated.top + y, drawMask, color, priority, 0); + const byte color = EGAmapping[bitmap[x]]; + const int x2 = clipRectTranslated.left + x; + const int y2 = clipRectTranslated.top + y; + if (color != clearKey && priority >= _screen->getPriority(x2, y2)) + _screen->putPixel(x2, y2, drawMask, color, priority, 0); } } } } -// We don't fully follow sierra sci here, I did the scaling algo myself and it's definitely not pixel-perfect -// with the one sierra is using. It shouldn't matter because the scaled cel rect is definitely the same as in sierra sci -void GfxView::drawScaled(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRectTranslated, int16 loopNo, int16 celNo, byte priority, int16 scaleX, int16 scaleY) { - Palette *palette = _embeddedPal ? &_viewPalette : &_palette->_sysPalette; - CelInfo *celInfo = getCelInfo(loopNo, celNo); - byte *bitmap = getBitmap(loopNo, celNo); - int16 celHeight = celInfo->height, celWidth = celInfo->width; - byte clearKey = celInfo->clearKey; - byte color; - byte drawMask = priority == 255 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY; - int x, y; - uint16 scalingX[320]; - uint16 scalingY[200]; +/** + * We don't fully follow sierra sci here, I did the scaling algo myself and it + * is definitely not pixel-perfect with the one sierra is using. It shouldn't + * matter because the scaled cel rect is definitely the same as in sierra sci. + */ +void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, const Common::Rect &clipRectTranslated, + int16 loopNo, int16 celNo, byte priority, int16 scaleX, int16 scaleY) { + const Palette *palette = _embeddedPal ? &_viewPalette : &_palette->_sysPalette; + const CelInfo *celInfo = getCelInfo(loopNo, celNo); + const byte *bitmap = getBitmap(loopNo, celNo); + const int16 celHeight = celInfo->height; + const int16 celWidth = celInfo->width; + const byte clearKey = celInfo->clearKey; + const byte drawMask = (priority == 255) ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY; + uint16 scalingX[640]; + uint16 scalingY[480]; int16 scaledWidth, scaledHeight; int16 pixelNo, scaledPixel, scaledPixelNo, prevScaledPixelNo; - uint16 offsetX, offsetY; if (_embeddedPal) { // Merge view palette in... @@ -590,6 +633,7 @@ void GfxView::drawScaled(Common::Rect rect, Common::Rect clipRect, Common::Rect scaledPixel = scaledPixelNo = prevScaledPixelNo = 0; while (pixelNo < celHeight) { scaledPixelNo = scaledPixel >> 7; + assert(scaledPixelNo < ARRAYSIZE(scalingY)); if (prevScaledPixelNo < scaledPixelNo) memset(&scalingY[prevScaledPixelNo], pixelNo, scaledPixelNo - prevScaledPixelNo); scalingY[scaledPixelNo] = pixelNo; @@ -606,6 +650,7 @@ void GfxView::drawScaled(Common::Rect rect, Common::Rect clipRect, Common::Rect scaledPixel = scaledPixelNo = prevScaledPixelNo = 0; while (pixelNo < celWidth) { scaledPixelNo = scaledPixel >> 7; + assert(scaledPixelNo < ARRAYSIZE(scalingX)); if (prevScaledPixelNo < scaledPixelNo) memset(&scalingX[prevScaledPixelNo], pixelNo, scaledPixelNo - prevScaledPixelNo); scalingX[scaledPixelNo] = pixelNo; @@ -620,27 +665,25 @@ void GfxView::drawScaled(Common::Rect rect, Common::Rect clipRect, Common::Rect scaledWidth = MIN(clipRect.width(), scaledWidth); scaledHeight = MIN(clipRect.height(), scaledHeight); - offsetY = clipRect.top - rect.top; - offsetX = clipRect.left - rect.left; + const int16 offsetY = clipRect.top - rect.top; + const int16 offsetX = clipRect.left - rect.left; + + // Happens in SQ6, first room + if (offsetX < 0 || offsetY < 0) + return; - for (y = 0; y < scaledHeight; y++) { - for (x = 0; x < scaledWidth; x++) { - color = bitmap[scalingY[y + offsetY] * celWidth + scalingX[x + offsetX]]; - if (color != clearKey && priority >= _screen->getPriority(clipRectTranslated.left + x, clipRectTranslated.top + y)) { - _screen->putPixel(clipRectTranslated.left + x, clipRectTranslated.top + y, drawMask, palette->mapping[color], priority, 0); + assert(scaledHeight + offsetY <= ARRAYSIZE(scalingY)); + assert(scaledWidth + offsetX <= ARRAYSIZE(scalingX)); + for (int y = 0; y < scaledHeight; y++) { + for (int x = 0; x < scaledWidth; x++) { + const byte color = bitmap[scalingY[y + offsetY] * celWidth + scalingX[x + offsetX]]; + const int x2 = clipRectTranslated.left + x; + const int y2 = clipRectTranslated.top + y; + if (color != clearKey && priority >= _screen->getPriority(x2, y2)) { + _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0); } } } } -uint16 GfxView::getCelCount(int16 loopNo) { - if ((loopNo < 0) || (loopNo >= _loopCount)) - return 0; - return _loop[loopNo].celCount; -} - -Palette *GfxView::getPalette() { - return _embeddedPal ? &_viewPalette : &_palette->_sysPalette; -} - } // End of namespace Sci diff --git a/engines/sci/graphics/view.h b/engines/sci/graphics/view.h index a2050dc9d5..6eb1830b99 100644 --- a/engines/sci/graphics/view.h +++ b/engines/sci/graphics/view.h @@ -60,20 +60,21 @@ public: GfxView(ResourceManager *resMan, GfxScreen *screen, GfxPalette *palette, GuiResourceId resourceId); ~GfxView(); - GuiResourceId getResourceId(); - int16 getWidth(int16 loopNo, int16 celNo); - int16 getHeight(int16 loopNo, int16 celNo); - CelInfo *getCelInfo(int16 loopNo, int16 celNo); - LoopInfo *getLoopInfo(int16 loopNo); - void getCelRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, Common::Rect *outRect); - void getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, int16 scaleX, int16 scaleY, Common::Rect *outRect); - byte *getBitmap(int16 loopNo, int16 celNo); - void draw(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRectTranslated, int16 loopNo, int16 celNo, byte priority, uint16 EGAmappingNr, bool upscaledHires); - void drawScaled(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRectTranslated, int16 loopNo, int16 celNo, byte priority, int16 scaleX, int16 scaleY); + GuiResourceId getResourceId() const; + int16 getWidth(int16 loopNo, int16 celNo) const; + int16 getHeight(int16 loopNo, int16 celNo) const; + const CelInfo *getCelInfo(int16 loopNo, int16 celNo) const; + void getCelRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, Common::Rect &outRect) const; + void getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, int16 scaleX, int16 scaleY, Common::Rect &outRect) const; + const byte *getBitmap(int16 loopNo, int16 celNo); + void draw(const Common::Rect &rect, const Common::Rect &clipRect, const Common::Rect &clipRectTranslated, int16 loopNo, int16 celNo, byte priority, uint16 EGAmappingNr, bool upscaledHires); + void drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, const Common::Rect &clipRectTranslated, int16 loopNo, int16 celNo, byte priority, int16 scaleX, int16 scaleY); uint16 getLoopCount() const { return _loopCount; } - uint16 getCelCount(int16 loopNo); + uint16 getCelCount(int16 loopNo) const; Palette *getPalette(); + bool isSci2Hires(); + private: void initData(GuiResourceId resourceId); void unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCount); @@ -86,12 +87,16 @@ private: GuiResourceId _resourceId; Resource *_resource; byte *_resourceData; + int _resourceSize; uint16 _loopCount; LoopInfo *_loop; bool _embeddedPal; Palette _viewPalette; + // set for SCI2 views in gk1/windows, means that views are hires and should be handled accordingly + bool _isSci2Hires; + byte *_EGAmapping; }; diff --git a/engines/sci/module.mk b/engines/sci/module.mk index a2cfd38f95..85988b8f1b 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -10,7 +10,6 @@ MODULE_OBJS := \ sci.o \ util.o \ engine/features.o \ - engine/game.o \ engine/gc.o \ engine/kernel.o \ engine/kevent.o \ @@ -44,7 +43,6 @@ MODULE_OBJS := \ graphics/cursor.o \ graphics/font.o \ graphics/fontsjis.o \ - graphics/gui.o \ graphics/maciconbar.o \ graphics/menu.o \ graphics/paint.o \ @@ -69,9 +67,6 @@ MODULE_OBJS := \ sound/drivers/fb01.o \ sound/drivers/midi.o \ sound/drivers/pcjr.o \ - sound/iterator/core.o \ - sound/iterator/iterator.o \ - sound/iterator/songlib.o \ video/seq_decoder.o @@ -79,7 +74,6 @@ ifdef ENABLE_SCI32 MODULE_OBJS += \ engine/kernel32.o \ graphics/frameout.o \ - graphics/gui32.o \ graphics/paint32.o \ graphics/robot.o \ video/vmd_decoder.o diff --git a/engines/sci/parser/vocabulary.cpp b/engines/sci/parser/vocabulary.cpp index 00448f5d51..e48a9cdfda 100644 --- a/engines/sci/parser/vocabulary.cpp +++ b/engines/sci/parser/vocabulary.cpp @@ -33,59 +33,6 @@ namespace Sci { -#if 0 - -#define VOCAB_RESOURCE_CLASSES 996 -/** - * Vocabulary class names. - * These strange names were taken from an SCI01 interpreter. - */ -const char *class_names[] = {"", - "", - "conj", // conjunction - "ass", // ? - "pos", // preposition ? - "art", // article - "adj", // adjective - "pron", // pronoun - "noun", // noun - "auxv", // auxillary verb - "adv", // adverb - "verb", // verb - "", - "", - "", - "" - }; - -int *vocab_get_classes(ResourceManager *resMan, int* count) { - Resource* r; - int *c; - unsigned int i; - - if ((r = resMan->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_CLASSES), 0)) == NULL) - return 0; - - c = (int *)malloc(sizeof(int) * r->size / 2); - for (i = 2; i < r->size; i += 4) { - c[i/4] = READ_LE_UINT16(r->data + i); - } - *count = r->size / 4; - - return c; -} - -int vocab_get_class_count(ResourceManager *resMan) { - Resource* r; - - if ((r = resMan->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_CLASSES), 0)) == 0) - return 0; - - return r->size / 4; -} - -#endif - Vocabulary::Vocabulary(ResourceManager *resMan) : _resMan(resMan) { _parserRules = NULL; _vocabVersion = kVocabularySCI0; diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 400f0b1e67..2958ca1e3b 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -26,8 +26,11 @@ // Resource library #include "common/file.h" +#include "common/fs.h" +#include "common/macresman.h" #include "sci/resource.h" +#include "sci/resource_intern.h" #include "sci/util.h" namespace Sci { @@ -111,7 +114,7 @@ static const char *resourceTypeNames[] = { "memory", "vocab", "font", "cursor", "patch", "bitmap", "palette", "cdaudio", "audio", "sync", "message", "map", "heap", - "audio36", "sync36", "", "", "robot" + "audio36", "sync36", "", "", "robot", "vmd" }; static const char *resourceTypeSuffixes[] = { @@ -119,7 +122,7 @@ static const char *resourceTypeSuffixes[] = { " ", "voc", "fon", "cur", "pat", "bit", "pal", "cda", "aud", "syn", "msg", "map", "hep", "aud", "syn", - "trn", " ", "rbt" + "trn", " ", "rbt", "vmd" }; const char *getResourceTypeName(ResourceType restype) { @@ -130,7 +133,7 @@ const char *getResourceTypeName(ResourceType restype) { } //-- Resource main functions -- -Resource::Resource() { +Resource::Resource(ResourceId id) : _id(id) { data = NULL; size = 0; _fileOffset = 0; @@ -143,7 +146,7 @@ Resource::Resource() { Resource::~Resource() { delete[] data; - if (_source && _source->source_type == kSourcePatch) + if (_source && _source->getSourceType() == kSourcePatch) delete _source; } @@ -154,102 +157,76 @@ void Resource::unalloc() { } void Resource::writeToStream(Common::WriteStream *stream) const { - stream->writeByte(_id.type | 0x80); // 0x80 is required by old sierra sci, otherwise it wont accept the patch file + stream->writeByte(getType() | 0x80); // 0x80 is required by old sierra sci, otherwise it wont accept the patch file stream->writeByte(_headerSize); if (_headerSize > 0) stream->write(_header, _headerSize); stream->write(data, size); } -uint32 Resource::getAudioCompressionType() { - return _source->audioCompressionType; +uint32 Resource::getAudioCompressionType() const { + return _source->getAudioCompressionType(); } -//-- resMan helper functions -- +uint32 AudioVolumeResourceSource::getAudioCompressionType() const { + return _audioCompressionType; +} -// Resource source list management -ResourceSource *ResourceManager::addExternalMap(const char *file_name, int volume_nr) { - ResourceSource *newsrc = new ResourceSource(); +ResourceSource::ResourceSource(ResSourceType type, const Common::String &name, int volNum, const Common::FSNode *resFile) + : _sourceType(type), _name(name), _volumeNumber(volNum), _resourceFile(resFile) { + _scanned = false; +} - newsrc->source_type = kSourceExtMap; - newsrc->location_name = file_name; - newsrc->resourceFile = 0; - newsrc->scanned = false; - newsrc->associated_map = NULL; - newsrc->volume_number = volume_nr; +ResourceSource::~ResourceSource() { +} - _sources.push_back(newsrc); - return newsrc; +MacResourceForkResourceSource::MacResourceForkResourceSource(const Common::String &name, int volNum) + : ResourceSource(kSourceMacResourceFork, name, volNum) { + _macResMan = new Common::MacResManager(); + assert(_macResMan); } -ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile, int volume_nr) { - ResourceSource *newsrc = new ResourceSource(); +MacResourceForkResourceSource::~MacResourceForkResourceSource() { + delete _macResMan; +} - newsrc->source_type = kSourceExtMap; - newsrc->location_name = mapFile->getName(); - newsrc->resourceFile = mapFile; - newsrc->scanned = false; - newsrc->associated_map = NULL; - newsrc->volume_number = volume_nr; +//-- resMan helper functions -- + +// Resource source list management + +ResourceSource *ResourceManager::addExternalMap(const Common::String &filename, int volume_nr) { + ResourceSource *newsrc = new ExtMapResourceSource(filename, volume_nr); _sources.push_back(newsrc); return newsrc; } -ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType type, const char *filename, int number) { - ResourceSource *newsrc = new ResourceSource(); - - newsrc->source_type = type; - newsrc->scanned = false; - newsrc->location_name = filename; - newsrc->resourceFile = 0; - newsrc->volume_number = number; - newsrc->associated_map = map; - newsrc->audioCompressionType = 0; - newsrc->audioCompressionOffsetMapping = NULL; - if (type == kSourceAudioVolume) - checkIfAudioVolumeIsCompressed(newsrc); +ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile, int volume_nr) { + ResourceSource *newsrc = new ExtMapResourceSource(mapFile->getName(), volume_nr, mapFile); _sources.push_back(newsrc); return newsrc; } -ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType type, const Common::FSNode *resFile, int number) { - ResourceSource *newsrc = new ResourceSource(); - - newsrc->source_type = type; - newsrc->scanned = false; - newsrc->location_name = resFile->getName(); - newsrc->resourceFile = resFile; - newsrc->volume_number = number; - newsrc->associated_map = map; - newsrc->audioCompressionType = 0; - newsrc->audioCompressionOffsetMapping = NULL; - if (type == kSourceAudioVolume) - checkIfAudioVolumeIsCompressed(newsrc); +ResourceSource *ResourceManager::addSource(ResourceSource *newsrc) { + assert(newsrc); _sources.push_back(newsrc); return newsrc; } -ResourceSource *ResourceManager::addPatchDir(const char *dirname) { - ResourceSource *newsrc = new ResourceSource(); - - newsrc->source_type = kSourceDirectory; - newsrc->resourceFile = 0; - newsrc->scanned = false; - newsrc->location_name = dirname; +ResourceSource *ResourceManager::addPatchDir(const Common::String &dirname) { + ResourceSource *newsrc = new DirectoryResourceSource(dirname); _sources.push_back(newsrc); return 0; } -ResourceSource *ResourceManager::getVolume(ResourceSource *map, int volume_nr) { +ResourceSource *ResourceManager::findVolume(ResourceSource *map, int volume_nr) { for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) { - ResourceSource *src = *it; - if ((src->source_type == kSourceVolume || src->source_type == kSourceAudioVolume) - && src->associated_map == map && src->volume_number == volume_nr) + ResourceSource *src = (*it)->findVolume(map, volume_nr); + if (src) return src; } @@ -258,7 +235,9 @@ ResourceSource *ResourceManager::getVolume(ResourceSource *map, int volume_nr) { // Resource manager constructors and operations -bool ResourceManager::loadPatch(Resource *res, Common::SeekableReadStream *file) { +bool Resource::loadPatch(Common::SeekableReadStream *file) { + Resource *res = this; + // We assume that the resource type matches res->type // We also assume that the current file position is right at the actual data (behind resourceid/headersize byte) @@ -286,27 +265,27 @@ bool ResourceManager::loadPatch(Resource *res, Common::SeekableReadStream *file) return true; } -bool ResourceManager::loadFromPatchFile(Resource *res) { +bool Resource::loadFromPatchFile() { Common::File file; - const char *filename = res->_source->location_name.c_str(); + const Common::String &filename = _source->getLocationName(); if (file.open(filename) == false) { - warning("Failed to open patch file %s", filename); - res->unalloc(); + warning("Failed to open patch file %s", filename.c_str()); + unalloc(); return false; } // Skip resourceid and header size byte file.seek(2, SEEK_SET); - return loadPatch(res, &file); + return loadPatch(&file); } Common::SeekableReadStream *ResourceManager::getVolumeFile(ResourceSource *source) { Common::List<Common::File *>::iterator it = _volumeFiles.begin(); Common::File *file; - if (source->resourceFile) - return source->resourceFile->createReadStream(); + if (source->_resourceFile) + return source->_resourceFile->createReadStream(); - const char *filename = source->location_name.c_str(); + const char *filename = source->getLocationName().c_str(); // check if file is already opened while (it != _volumeFiles.end()) { @@ -340,107 +319,131 @@ Common::SeekableReadStream *ResourceManager::getVolumeFile(ResourceSource *sourc static uint32 resTypeToMacTag(ResourceType type); void ResourceManager::loadResource(Resource *res) { - if (res->_source->source_type == kSourcePatch && loadFromPatchFile(res)) - return; + res->_source->loadResource(this, res); +} - if (res->_source->source_type == kSourceMacResourceFork) { - Common::SeekableReadStream *stream = res->_source->macResMan.getResource(resTypeToMacTag(res->_id.type), res->_id.number); - if (!stream) - error("Could not get Mac resource fork resource: %d %d", res->_id.type, res->_id.number); +void PatchResourceSource::loadResource(ResourceManager *resMan, Resource *res) { + bool result = res->loadFromPatchFile(); + if (!result) { + // TODO: We used to fallback to the "default" code here if loadFromPatchFile + // failed, but I am not sure whether that is really appropriate. + // In fact it looks like a bug to me, so I commented this out for now. + //ResourceSource::loadResource(res); + } +} - int error = decompress(res, stream); - if (error) { - warning("Error %d occured while reading %s from Mac resource file: %s", - error, res->_id.toString().c_str(), sci_error_types[error]); - res->unalloc(); - } - return; +void MacResourceForkResourceSource::loadResource(ResourceManager *resMan, Resource *res) { + Common::SeekableReadStream *stream = _macResMan->getResource(resTypeToMacTag(res->getType()), res->getNumber()); + + if (!stream) + error("Could not get Mac resource fork resource: %d %d", res->getType(), res->getNumber()); + + int error = res->decompress(resMan->getVolVersion(), stream); + if (error) { + warning("Error %d occurred while reading %s from Mac resource file: %s", + error, res->_id.toString().c_str(), sci_error_types[error]); + res->unalloc(); } +} - Common::SeekableReadStream *fileStream = getVolumeFile(res->_source); +Common::SeekableReadStream *ResourceSource::getVolumeFile(ResourceManager *resMan, Resource *res) { + Common::SeekableReadStream *fileStream = resMan->getVolumeFile(this); if (!fileStream) { - warning("Failed to open %s", res->_source->location_name.c_str()); - res->unalloc(); - return; + warning("Failed to open %s", getLocationName().c_str()); + if (res) + res->unalloc(); } - switch(res->_source->source_type) { - case kSourceWave: - fileStream->seek(res->_fileOffset, SEEK_SET); - loadFromWaveFile(res, fileStream); - if (res->_source->resourceFile) - delete fileStream; + return fileStream; +} + +void WaveResourceSource::loadResource(ResourceManager *resMan, Resource *res) { + Common::SeekableReadStream *fileStream = getVolumeFile(resMan, res); + if (!fileStream) return; - case kSourceAudioVolume: - if (res->_source->audioCompressionType) { - // this file is compressed, so lookup our offset in the offset-translation table and get the new offset - // also calculate the compressed size by using the next offset - int32 *mappingTable = res->_source->audioCompressionOffsetMapping; - int32 compressedOffset = 0; - - do { - if (*mappingTable == res->_fileOffset) { - mappingTable++; - compressedOffset = *mappingTable; - // Go to next compressed offset and use that to calculate size of compressed sample - switch (res->_id.type) { - case kResourceTypeSync: - case kResourceTypeSync36: - // we should already have a (valid) size - break; - default: - mappingTable += 2; - res->size = *mappingTable - compressedOffset; - } + fileStream->seek(res->_fileOffset, SEEK_SET); + res->loadFromWaveFile(fileStream); + if (_resourceFile) + delete fileStream; +} + +void AudioVolumeResourceSource::loadResource(ResourceManager *resMan, Resource *res) { + Common::SeekableReadStream *fileStream = getVolumeFile(resMan, res); + if (!fileStream) + return; + + if (_audioCompressionType) { + // this file is compressed, so lookup our offset in the offset-translation table and get the new offset + // also calculate the compressed size by using the next offset + int32 *mappingTable = _audioCompressionOffsetMapping; + int32 compressedOffset = 0; + + do { + if (*mappingTable == res->_fileOffset) { + mappingTable++; + compressedOffset = *mappingTable; + // Go to next compressed offset and use that to calculate size of compressed sample + switch (res->getType()) { + case kResourceTypeSync: + case kResourceTypeSync36: + // we should already have a (valid) size break; + default: + mappingTable += 2; + res->size = *mappingTable - compressedOffset; } - mappingTable += 2; - } while (*mappingTable); - - if (!compressedOffset) - error("could not translate offset to compressed offset in audio volume"); - fileStream->seek(compressedOffset, SEEK_SET); - - switch (res->_id.type) { - case kResourceTypeAudio: - case kResourceTypeAudio36: - // Directly read the stream, compressed audio wont have resource type id and header size for SCI1.1 - loadFromAudioVolumeSCI1(res, fileStream); - if (res->_source->resourceFile) - delete fileStream; - return; - default: break; } - } else { - // original file, directly seek to given offset and get SCI1/SCI1.1 audio resource - fileStream->seek(res->_fileOffset, SEEK_SET); + mappingTable += 2; + } while (*mappingTable); + + if (!compressedOffset) + error("could not translate offset to compressed offset in audio volume"); + fileStream->seek(compressedOffset, SEEK_SET); + + switch (res->getType()) { + case kResourceTypeAudio: + case kResourceTypeAudio36: + // Directly read the stream, compressed audio wont have resource type id and header size for SCI1.1 + res->loadFromAudioVolumeSCI1(fileStream); + if (_resourceFile) + delete fileStream; + return; + default: + break; } - if (getSciVersion() < SCI_VERSION_1_1) - loadFromAudioVolumeSCI1(res, fileStream); - else - loadFromAudioVolumeSCI11(res, fileStream); + } else { + // original file, directly seek to given offset and get SCI1/SCI1.1 audio resource + fileStream->seek(res->_fileOffset, SEEK_SET); + } + if (getSciVersion() < SCI_VERSION_1_1) + res->loadFromAudioVolumeSCI1(fileStream); + else + res->loadFromAudioVolumeSCI11(fileStream); - if (res->_source->resourceFile) - delete fileStream; - return; + if (_resourceFile) + delete fileStream; +} - default: - fileStream->seek(res->_fileOffset, SEEK_SET); - int error = decompress(res, fileStream); +void ResourceSource::loadResource(ResourceManager *resMan, Resource *res) { + Common::SeekableReadStream *fileStream = getVolumeFile(resMan, res); + if (!fileStream) + return; - if (res->_source->resourceFile) - delete fileStream; + fileStream->seek(res->_fileOffset, SEEK_SET); - if (error) { - warning("Error %d occured while reading %s from resource file: %s", - error, res->_id.toString().c_str(), sci_error_types[error]); - res->unalloc(); - } + int error = res->decompress(resMan->getVolVersion(), fileStream); + if (error) { + warning("Error %d occurred while reading %s from resource file: %s", + error, res->_id.toString().c_str(), sci_error_types[error]); + res->unalloc(); } + + if (_resourceFile) + delete fileStream; } Resource *ResourceManager::testResource(ResourceId id) { @@ -461,12 +464,12 @@ int ResourceManager::addAppropriateSources() { const char *dot = strrchr(name.c_str(), '.'); int number = atoi(dot + 1); - addSource(map, kSourceVolume, name.c_str(), number); + addSource(new VolumeResourceSource(name, map, number)); } #ifdef ENABLE_SCI32 // GK1CD hires content if (Common::File::exists("alt.map") && Common::File::exists("resource.alt")) - addSource(addExternalMap("alt.map", 10), kSourceVolume, "resource.alt", 10); + addSource(new VolumeResourceSource("resource.alt", addExternalMap("alt.map", 10), 10)); #endif } else if (Common::File::exists("Data1")) { // Mac SCI1.1+ file naming scheme @@ -474,18 +477,19 @@ int ResourceManager::addAppropriateSources() { for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { Common::String filename = (*x)->getName(); - addSource(0, kSourceMacResourceFork, filename.c_str(), atoi(filename.c_str() + 4)); + addSource(new MacResourceForkResourceSource(filename, atoi(filename.c_str() + 4))); } #ifdef ENABLE_SCI32 // Mac SCI32 games have extra folders for patches addPatchDir("Robot Folder"); addPatchDir("Sound Folder"); addPatchDir("Voices Folder"); + addPatchDir("Voices"); //addPatchDir("VMD Folder"); // There can also be a "Patches" resource fork with patches if (Common::File::exists("Patches")) - addSource(0, kSourceMacResourceFork, "Patches", 100); + addSource(new MacResourceForkResourceSource("Patches", 100)); } else { // SCI2.1-SCI3 file naming scheme Common::ArchiveMemberList mapFiles; @@ -505,7 +509,7 @@ int ResourceManager::addAppropriateSources() { int resNumber = atoi(strrchr(resName.c_str(), '.') + 1); if (mapNumber == resNumber) { - addSource(addExternalMap(mapName.c_str(), mapNumber), kSourceVolume, resName.c_str(), mapNumber); + addSource(new VolumeResourceSource(resName, addExternalMap(mapName, mapNumber), mapNumber)); break; } } @@ -514,7 +518,7 @@ int ResourceManager::addAppropriateSources() { // SCI2.1 resource patches if (Common::File::exists("resmap.pat") && Common::File::exists("ressci.pat")) { // We add this resource with a map which surely won't exist - addSource(addExternalMap("resmap.pat", 100), kSourceVolume, "ressci.pat", 100); + addSource(new VolumeResourceSource("ressci.pat", addExternalMap("resmap.pat", 100), 100)); } } #else @@ -524,7 +528,7 @@ int ResourceManager::addAppropriateSources() { addPatchDir("."); if (Common::File::exists("message.map")) - addSource(addExternalMap("message.map"), kSourceVolume, "resource.msg", 0); + addSource(new VolumeResourceSource("resource.msg", addExternalMap("message.map"), 0)); return 1; } @@ -568,7 +572,7 @@ int ResourceManager::addAppropriateSources(const Common::FSList &fslist) { #ifdef ENABLE_SCI32 if (sci21PatchMap && sci21PatchRes) - addSource(sci21PatchMap, kSourceVolume, sci21PatchRes, 100); + addSource(new VolumeResourceSource(sci21PatchRes->getName(), sci21PatchMap, 100, sci21PatchRes)); #endif // Now find all the resource.0?? files @@ -583,7 +587,7 @@ int ResourceManager::addAppropriateSources(const Common::FSList &fslist) { const char *dot = strrchr(filename.c_str(), '.'); int number = atoi(dot + 1); - addSource(map, kSourceVolume, file, number); + addSource(new VolumeResourceSource(file->getName(), map, number, file)); } } @@ -598,12 +602,12 @@ int ResourceManager::addInternalSources() { Common::List<ResourceId>::iterator itr = resources->begin(); while (itr != resources->end()) { - ResourceSource *src = addSource(NULL, kSourceIntMap, "MAP", itr->number); + ResourceSource *src = addSource(new IntMapResourceSource("MAP", itr->getNumber())); - if ((itr->number == 65535) && Common::File::exists("RESOURCE.SFX")) - addSource(src, kSourceAudioVolume, "RESOURCE.SFX", 0); + if ((itr->getNumber() == 65535) && Common::File::exists("RESOURCE.SFX")) + addSource(new AudioVolumeResourceSource(this, "RESOURCE.SFX", src, 0)); else if (Common::File::exists("RESOURCE.AUD")) - addSource(src, kSourceAudioVolume, "RESOURCE.AUD", 0); + addSource(new AudioVolumeResourceSource(this, "RESOURCE.AUD", src, 0)); ++itr; } @@ -615,38 +619,39 @@ void ResourceManager::scanNewSources() { for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) { ResourceSource *source = *it; - if (!source->scanned) { - source->scanned = true; - switch (source->source_type) { - case kSourceDirectory: - readResourcePatches(source); -#ifdef ENABLE_SCI32 - readResourcePatchesBase36(source); -#endif - readWaveAudioPatches(); - break; - case kSourceExtMap: - if (_mapVersion < kResVersionSci1Late) - readResourceMapSCI0(source); - else - readResourceMapSCI1(source); - break; - case kSourceExtAudioMap: - readAudioMapSCI1(source); - break; - case kSourceIntMap: - readAudioMapSCI11(source); - break; - case kSourceMacResourceFork: - readMacResourceFork(source); - break; - default: - break; - } + if (!source->_scanned) { + source->_scanned = true; + source->scanSource(this); } } } +void DirectoryResourceSource::scanSource(ResourceManager *resMan) { + resMan->readResourcePatches(); + + // We can't use getSciVersion() at this point, thus using _volVersion + if (resMan->_volVersion >= kResVersionSci11) // SCI1.1+ + resMan->readResourcePatchesBase36(); + + resMan->readWaveAudioPatches(); +} + +void ExtMapResourceSource::scanSource(ResourceManager *resMan) { + if (resMan->_mapVersion < kResVersionSci1Late) + resMan->readResourceMapSCI0(this); + else + resMan->readResourceMapSCI1(this); +} + +void ExtAudioMapResourceSource::scanSource(ResourceManager *resMan) { + resMan->readAudioMapSCI1(this); +} + +void IntMapResourceSource::scanSource(ResourceManager *resMan) { + resMan->readAudioMapSCI11(this); +} + + void ResourceManager::freeResourceSources() { for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) delete *it; @@ -655,13 +660,6 @@ void ResourceManager::freeResourceSources() { } ResourceManager::ResourceManager() { - addAppropriateSources(); - init(); -} - -ResourceManager::ResourceManager(const Common::FSList &fslist) { - addAppropriateSources(fslist); - init(); } void ResourceManager::init() { @@ -716,7 +714,7 @@ void ResourceManager::init() { debugC(1, kDebugLevelResMan, "resMan: Detected Amiga graphic resources"); break; default: - warning("resMan: Couldn't determine view type"); + error("resMan: Couldn't determine view type"); } } @@ -795,7 +793,7 @@ Common::List<ResourceId> *ResourceManager::listResources(ResourceType type, int ResourceMap::iterator itr = _resMap.begin(); while (itr != _resMap.end()) { - if ((itr->_value->_id.type == type) && ((mapNumber == -1) || (itr->_value->_id.number == mapNumber))) + if ((itr->_value->getType() == type) && ((mapNumber == -1) || (itr->_value->getNumber() == mapNumber))) resources->push_back(itr->_value->_id); ++itr; } @@ -813,7 +811,7 @@ Resource *ResourceManager::findResource(ResourceId id, bool lock) { loadResource(retval); else if (retval->_status == kResStatusEnqueued) removeFromLRU(retval); - // Unless an error occured, the resource is now either + // Unless an error occurred, the resource is now either // locked or allocated, but never queued or freed. freeOldResources(); @@ -876,7 +874,7 @@ const char *ResourceManager::versionDescription(ResVersion version) const { return "Version not valid"; } -ResourceManager::ResVersion ResourceManager::detectMapVersion() { +ResVersion ResourceManager::detectMapVersion() { Common::SeekableReadStream *fileStream = 0; byte buff[6]; ResourceSource *rsrc= 0; @@ -884,17 +882,17 @@ ResourceManager::ResVersion ResourceManager::detectMapVersion() { for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) { rsrc = *it; - if (rsrc->source_type == kSourceExtMap) { - if (rsrc->resourceFile) { - fileStream = rsrc->resourceFile->createReadStream(); + if (rsrc->getSourceType() == kSourceExtMap) { + if (rsrc->_resourceFile) { + fileStream = rsrc->_resourceFile->createReadStream(); } else { Common::File *file = new Common::File(); - file->open(rsrc->location_name); + file->open(rsrc->getLocationName()); if (file->isOpen()) fileStream = file; } break; - } else if (rsrc->source_type == kSourceMacResourceFork) + } else if (rsrc->getSourceType() == kSourceMacResourceFork) return kResVersionSci11Mac; } @@ -909,7 +907,7 @@ ResourceManager::ResVersion ResourceManager::detectMapVersion() { // check if 0 or 01 - try to read resources in SCI0 format and see if exists fileStream->seek(0, SEEK_SET); while (fileStream->read(buff, 6) == 6 && !(buff[0] == 0xFF && buff[1] == 0xFF && buff[2] == 0xFF)) { - if (getVolume(rsrc, (buff[5] & 0xFC) >> 2) == NULL) + if (findVolume(rsrc, (buff[5] & 0xFC) >> 2) == NULL) return kResVersionSci1Middle; } return kResVersionSci0Sci1Early; @@ -966,24 +964,24 @@ ResourceManager::ResVersion ResourceManager::detectMapVersion() { return kResVersionUnknown; } -ResourceManager::ResVersion ResourceManager::detectVolVersion() { +ResVersion ResourceManager::detectVolVersion() { Common::SeekableReadStream *fileStream = 0; ResourceSource *rsrc; for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it) { rsrc = *it; - if (rsrc->source_type == kSourceVolume) { - if (rsrc->resourceFile) { - fileStream = rsrc->resourceFile->createReadStream(); + if (rsrc->getSourceType() == kSourceVolume) { + if (rsrc->_resourceFile) { + fileStream = rsrc->_resourceFile->createReadStream(); } else { Common::File *file = new Common::File(); - file->open(rsrc->location_name); + file->open(rsrc->getLocationName()); if (file->isOpen()) fileStream = file; } break; - } else if (rsrc->source_type == kSourceMacResourceFork) + } else if (rsrc->getSourceType() == kSourceMacResourceFork) return kResVersionSci11Mac; } @@ -1068,41 +1066,41 @@ ResourceManager::ResVersion ResourceManager::detectVolVersion() { // version-agnostic patch application void ResourceManager::processPatch(ResourceSource *source, ResourceType resourceType, uint16 resourceNr, uint32 tuple) { Common::SeekableReadStream *fileStream = 0; - Resource *newrsc; + Resource *newrsc = 0; ResourceId resId = ResourceId(resourceType, resourceNr, tuple); - byte patchType, patchDataOffset; - int fsize; + ResourceType checkForType = resourceType; // base36 encoded patches (i.e. audio36 and sync36) have the same type as their non-base36 encoded counterparts - if (resourceType == kResourceTypeAudio36) - resourceType = kResourceTypeAudio; - - if (resourceType == kResourceTypeSync36) - resourceType = kResourceTypeSync; + if (checkForType == kResourceTypeAudio36) + checkForType = kResourceTypeAudio; + else if (checkForType == kResourceTypeSync36) + checkForType = kResourceTypeSync; - if (source->resourceFile) { - fileStream = source->resourceFile->createReadStream(); + if (source->_resourceFile) { + fileStream = source->_resourceFile->createReadStream(); } else { Common::File *file = new Common::File(); - if (!file->open(source->location_name)) { - warning("ResourceManager::processPatch(): failed to open %s", source->location_name.c_str()); + if (!file->open(source->getLocationName())) { + warning("ResourceManager::processPatch(): failed to open %s", source->getLocationName().c_str()); return; } fileStream = file; } - fsize = fileStream->size(); + + int fsize = fileStream->size(); if (fsize < 3) { - debug("Patching %s failed - file too small", source->location_name.c_str()); + debug("Patching %s failed - file too small", source->getLocationName().c_str()); return; } - patchType = fileStream->readByte() & 0x7F; - patchDataOffset = fileStream->readByte(); + byte patchType = fileStream->readByte() & 0x7F; + byte patchDataOffset = fileStream->readByte(); delete fileStream; - if (patchType != resourceType) { - debug("Patching %s failed - resource type mismatch", source->location_name.c_str()); + if (patchType != checkForType) { + debug("Patching %s failed - resource type mismatch", source->getLocationName().c_str()); + return; } // Fixes SQ5/German, patch file special case logic taken from SCI View disassembly @@ -1118,35 +1116,27 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource patchDataOffset = 8; break; default: - warning("Resource patch unsupported special case %X", patchDataOffset & 0x7F); + error("Resource patch unsupported special case %X", patchDataOffset & 0x7F); return; } } if (patchDataOffset + 2 >= fsize) { debug("Patching %s failed - patch starting at offset %d can't be in file of size %d", - source->location_name.c_str(), patchDataOffset + 2, fsize); + source->getLocationName().c_str(), patchDataOffset + 2, fsize); return; } - // Prepare destination, if neccessary - if (_resMap.contains(resId) == false) { - newrsc = new Resource; - _resMap.setVal(resId, newrsc); - } else - newrsc = _resMap.getVal(resId); + // Overwrite everything, because we're patching - newrsc->_id = resId; - newrsc->_status = kResStatusNoMalloc; - newrsc->_source = source; - newrsc->size = fsize - patchDataOffset - 2; + newrsc = updateResource(resId, source, fsize - patchDataOffset - 2); newrsc->_headerSize = patchDataOffset; newrsc->_fileOffset = 0; - debugC(1, kDebugLevelResMan, "Patching %s - OK", source->location_name.c_str()); -} -#ifdef ENABLE_SCI32 -void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { + debugC(1, kDebugLevelResMan, "Patching %s - OK", source->getLocationName().c_str()); +} + +void ResourceManager::readResourcePatchesBase36() { // The base36 encoded audio36 and sync36 resources use a different naming scheme, because they // cannot be described with a single resource number, but are a result of a // <number, noun, verb, cond, seq> tuple. Please don't be confused with the normal audio patches @@ -1176,42 +1166,61 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { name = (*x)->getName(); + inputName = (*x)->getName(); inputName.toUppercase(); - if (inputName.hasPrefix("BOOT")) // skip bootdisk.* - continue; - inputName.deleteChar(0); // delete the first character (type) inputName.deleteChar(7); // delete the dot // The base36 encoded resource contains the following: // uint16 resourceId, byte noun, byte verb, byte cond, byte seq - uint16 resourceNr = strtol(Common::String(inputName.c_str(), 3).c_str(), 0, 36); // 3 characters - byte noun = strtol(Common::String(inputName.c_str() + 3, 2).c_str(), 0, 36); // 2 characters - byte verb = strtol(Common::String(inputName.c_str() + 5, 2).c_str(), 0, 36); // 2 characters - byte cond = strtol(Common::String(inputName.c_str() + 7, 2).c_str(), 0, 36); // 2 characters - byte seq = strtol(Common::String(inputName.c_str() + 9, 1).c_str(), 0, 36); // 1 character - ResourceId resource36((ResourceType)i, resourceNr, noun, verb, cond, seq); - - /* - if (i == kResourceTypeAudio36) - debug("audio36 patch: %s => %s. tuple:%d, %s\n", name.c_str(), inputName.c_str(), resource36.tuple, resource36.toString().c_str()); - else - debug("sync36 patch: %s => %s. tuple:%d, %s\n", name.c_str(), inputName.c_str(), resource36.tuple, resource36.toString().c_str()); - */ - - psrcPatch = new ResourceSource; - psrcPatch->source_type = kSourcePatch; - psrcPatch->location_name = name; - psrcPatch->resourceFile = 0; - processPatch(psrcPatch, (ResourceType)i, resourceNr, resource36.tuple); + uint16 resourceNr = strtol(Common::String(inputName.c_str(), 3).c_str(), 0, 36); // 3 characters + uint16 noun = strtol(Common::String(inputName.c_str() + 3, 2).c_str(), 0, 36); // 2 characters + uint16 verb = strtol(Common::String(inputName.c_str() + 5, 2).c_str(), 0, 36); // 2 characters + uint16 cond = strtol(Common::String(inputName.c_str() + 7, 2).c_str(), 0, 36); // 2 characters + uint16 seq = strtol(Common::String(inputName.c_str() + 9, 1).c_str(), 0, 36); // 1 character + + // Check, if we got valid results + if ((noun <= 255) && (verb <= 255) && (cond <= 255) && (seq <= 255)) { + ResourceId resource36((ResourceType)i, resourceNr, noun, verb, cond, seq); + + /* + if (i == kResourceTypeAudio36) + debug("audio36 patch: %s => %s. tuple:%d, %s\n", name.c_str(), inputName.c_str(), resource36.tuple, resource36.toString().c_str()); + else + debug("sync36 patch: %s => %s. tuple:%d, %s\n", name.c_str(), inputName.c_str(), resource36.tuple, resource36.toString().c_str()); + */ + + // Make sure that the audio patch is a valid resource + if (i == kResourceTypeAudio36) { + Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name); + uint32 tag = stream->readUint32BE(); + + if (tag == MKID_BE('RIFF') || tag == MKID_BE('FORM')) { + delete stream; + processWavePatch(resource36, name); + continue; + } + + // Check for SOL as well + tag = (tag << 16) | stream->readUint16BE(); + + if (tag != MKID_BE('SOL\0')) { + delete stream; + continue; + } + + delete stream; + } + + psrcPatch = new PatchResourceSource(name); + processPatch(psrcPatch, (ResourceType)i, resourceNr, resource36.getTuple()); + } } } } -#endif - -void ResourceManager::readResourcePatches(ResourceSource *source) { +void ResourceManager::readResourcePatches() { // Note: since some SCI1 games(KQ5 floppy, SQ4) might use SCI0 naming scheme for patch files // this function tries to read patch file with any supported naming scheme, // regardless of s_sciVersion value @@ -1237,10 +1246,12 @@ void ResourceManager::readResourcePatches(ResourceSource *source) { for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { bool bAdd = false; name = (*x)->getName(); + // SCI1 scheme if (isdigit(name[0])) { - resourceNr = atoi(name.c_str()); - bAdd = true; + char *end = 0; + resourceNr = strtol(name.c_str(), &end, 10); + bAdd = (*end == '.'); // Ensure the next character is the period } else { // SCI0 scheme int resname_len = strlen(szResType); @@ -1252,10 +1263,7 @@ void ResourceManager::readResourcePatches(ResourceSource *source) { } if (bAdd) { - psrcPatch = new ResourceSource; - psrcPatch->source_type = kSourcePatch; - psrcPatch->location_name = name; - psrcPatch->resourceFile = 0; + psrcPatch = new PatchResourceSource(name); processPatch(psrcPatch, (ResourceType)i, resourceNr); } } @@ -1264,18 +1272,17 @@ void ResourceManager::readResourcePatches(ResourceSource *source) { int ResourceManager::readResourceMapSCI0(ResourceSource *map) { Common::SeekableReadStream *fileStream = 0; - Resource *res; ResourceType type; uint16 number, id; uint32 offset; - if (map->resourceFile) { - fileStream = map->resourceFile->createReadStream(); + if (map->_resourceFile) { + fileStream = map->_resourceFile->createReadStream(); if (!fileStream) return SCI_ERROR_RESMAP_NOT_FOUND; } else { Common::File *file = new Common::File(); - if (!file->open(map->location_name)) + if (!file->open(map->getLocationName())) return SCI_ERROR_RESMAP_NOT_FOUND; fileStream = file; } @@ -1291,7 +1298,7 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) { if (fileStream->eos() || fileStream->err()) { delete fileStream; - warning("Error while reading %s", map->location_name.c_str()); + warning("Error while reading %s", map->getLocationName().c_str()); return SCI_ERROR_RESMAP_NOT_FOUND; } if (offset == 0xFFFFFFFF) @@ -1302,9 +1309,8 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) { ResourceId resId = ResourceId(type, number); // adding a new resource if (_resMap.contains(resId) == false) { - res = new Resource; - res->_source = getVolume(map, offset >> bShift); - if (!res->_source) { + ResourceSource *source = findVolume(map, offset >> bShift); + if (!source) { warning("Could not get volume for resource %d, VolumeID %d", id, offset >> bShift); if (_mapVersion != _volVersion) { warning("Retrying with the detected volume version instead"); @@ -1312,12 +1318,11 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) { _mapVersion = _volVersion; bMask = (_mapVersion == kResVersionSci1Middle) ? 0xF0 : 0xFC; bShift = (_mapVersion == kResVersionSci1Middle) ? 28 : 26; - res->_source = getVolume(map, offset >> bShift); + source = findVolume(map, offset >> bShift); } } - res->_fileOffset = offset & (((~bMask) << 24) | 0xFFFFFF); - res->_id = resId; - _resMap.setVal(resId, res); + + addResource(resId, source, offset & (((~bMask) << 24) | 0xFFFFFF)); } } while (!fileStream->eos()); @@ -1327,15 +1332,14 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) { int ResourceManager::readResourceMapSCI1(ResourceSource *map) { Common::SeekableReadStream *fileStream = 0; - Resource *res; - if (map->resourceFile) { - fileStream = map->resourceFile->createReadStream(); + if (map->_resourceFile) { + fileStream = map->_resourceFile->createReadStream(); if (!fileStream) return SCI_ERROR_RESMAP_NOT_FOUND; } else { Common::File *file = new Common::File(); - if (!file->open(map->location_name)) + if (!file->open(map->getLocationName())) return SCI_ERROR_RESMAP_NOT_FOUND; fileStream = file; } @@ -1382,22 +1386,17 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { } if (fileStream->eos() || fileStream->err()) { delete fileStream; - warning("Error while reading %s", map->location_name.c_str()); + warning("Error while reading %s", map->getLocationName().c_str()); return SCI_ERROR_RESMAP_NOT_FOUND; } resId = ResourceId((ResourceType)type, number); // adding new resource only if it does not exist if (_resMap.contains(resId) == false) { - res = new Resource; - _resMap.setVal(resId, res); - res->_id = resId; - // NOTE: We add the map's volume number here to the specified volume number // for SCI2.1 and SCI3 maps that are not resmap.000. The resmap.* files' numbers // need to be used in concurrence with the volume specified in the map to get // the actual resource file. - res->_source = getVolume(map, volume_nr + map->volume_number); - res->_fileOffset = off; + addResource(resId, findVolume(map, volume_nr + map->_volumeNumber), off); } } } @@ -1438,11 +1437,11 @@ static uint32 resTypeToMacTag(ResourceType type) { return 0; } -int ResourceManager::readMacResourceFork(ResourceSource *source) { - if (!source->macResMan.open(source->location_name.c_str())) - error("%s is not a valid Mac resource fork", source->location_name.c_str()); +void MacResourceForkResourceSource::scanSource(ResourceManager *resMan) { + if (!_macResMan->open(getLocationName().c_str())) + error("%s is not a valid Mac resource fork", getLocationName().c_str()); - Common::MacResTagArray tagArray = source->macResMan.getResTagArray(); + Common::MacResTagArray tagArray = _macResMan->getResTagArray(); for (uint32 i = 0; i < tagArray.size(); i++) { ResourceType type = kResourceTypeInvalid; @@ -1457,11 +1456,11 @@ int ResourceManager::readMacResourceFork(ResourceSource *source) { if (type == kResourceTypeInvalid) continue; - Common::MacResIDArray idArray = source->macResMan.getResIDArray(tagArray[i]); + Common::MacResIDArray idArray = _macResMan->getResIDArray(tagArray[i]); for (uint32 j = 0; j < idArray.size(); j++) { // Get the size of the file - Common::SeekableReadStream *stream = source->macResMan.getResource(tagArray[i], idArray[j]); + Common::SeekableReadStream *stream = _macResMan->getResource(tagArray[i], idArray[j]); // Some IBIS resources have a size of 0, so we skip them if (!stream) @@ -1472,41 +1471,44 @@ int ResourceManager::readMacResourceFork(ResourceSource *source) { ResourceId resId = ResourceId(type, idArray[j]); - Resource *newrsc = NULL; - - // Prepare destination, if neccessary. Resource forks may contain patches. - if (!_resMap.contains(resId)) { - newrsc = new Resource; - _resMap.setVal(resId, newrsc); - } else - newrsc = _resMap.getVal(resId); - - // Overwrite everything - newrsc->_id = resId; - newrsc->_status = kResStatusNoMalloc; - newrsc->_source = source; - newrsc->size = fileSize; - newrsc->_headerSize = 0; + // Overwrite Resource instance. Resource forks may contain patches. + resMan->updateResource(resId, this, fileSize); } } - - return 0; } void ResourceManager::addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size) { // Adding new resource only if it does not exist if (_resMap.contains(resId) == false) { - Resource *res = new Resource; + Resource *res = new Resource(resId); _resMap.setVal(resId, res); - res->_id = resId; res->_source = src; res->_fileOffset = offset; res->size = size; } } -int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream *file, - uint32&szPacked, ResourceCompression &compression) { +Resource *ResourceManager::updateResource(ResourceId resId, ResourceSource *src, uint32 size) { + // Update a patched resource, whether it exists or not + Resource *res = 0; + + if (_resMap.contains(resId)) { + res = _resMap.getVal(resId); + } else { + res = new Resource(resId); + _resMap.setVal(resId, res); + } + + res->_status = kResStatusNoMalloc; + res->_source = src; + res->_headerSize = 0; + res->size = size; + + return res; +} + +int Resource::readResourceInfo(ResVersion volVersion, Common::SeekableReadStream *file, + uint32 &szPacked, ResourceCompression &compression) { // SCI0 volume format: {wResId wPacked+4 wUnpacked wCompression} = 8 bytes // SCI1 volume format: {bResType wResNumber wPacked+4 wUnpacked wCompression} = 9 bytes // SCI1.1 volume format: {bResType wResNumber wPacked wUnpacked wCompression} = 9 bytes @@ -1515,7 +1517,7 @@ int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream uint32 wCompression, szUnpacked; ResourceType type; - switch (_volVersion) { + switch (volVersion) { case kResVersionSci0Sci1Early: case kResVersionSci1Middle: w = file->readUint16LE(); @@ -1542,8 +1544,8 @@ int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream case kResVersionSci11Mac: // Doesn't store this data in the resource. Fortunately, // we already have this data. - type = res->_id.type; - number = res->_id.number; + type = getType(); + number = getNumber(); szPacked = file->size(); szUnpacked = file->size(); wCompression = 0; @@ -1565,8 +1567,8 @@ int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream if ((file->eos() || file->err())) return SCI_ERROR_IO_ERROR; - res->_id = ResourceId(type, number); - res->size = szUnpacked; + _id = ResourceId(type, number); + size = szUnpacked; // checking compression method switch (wCompression) { @@ -1602,15 +1604,15 @@ int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream return compression == kCompUnknown ? SCI_ERROR_UNKNOWN_COMPRESSION : 0; } -int ResourceManager::decompress(Resource *res, Common::SeekableReadStream *file) { - int error; +int Resource::decompress(ResVersion volVersion, Common::SeekableReadStream *file) { + int errorNum; uint32 szPacked = 0; ResourceCompression compression = kCompUnknown; // fill resource info - error = readResourceInfo(res, file, szPacked, compression); - if (error) - return error; + errorNum = readResourceInfo(volVersion, file, szPacked, compression); + if (errorNum) + return errorNum; // getting a decompressor Decompressor *dec = NULL; @@ -1636,18 +1638,18 @@ int ResourceManager::decompress(Resource *res, Common::SeekableReadStream *file) break; #endif default: - warning("Resource %s: Compression method %d not supported", res->_id.toString().c_str(), compression); + error("Resource %s: Compression method %d not supported", _id.toString().c_str(), compression); return SCI_ERROR_UNKNOWN_COMPRESSION; } - res->data = new byte[res->size]; - res->_status = kResStatusAllocated; - error = res->data ? dec->unpack(file, res->data, szPacked, res->size) : SCI_ERROR_RESOURCE_TOO_BIG; - if (error) - res->unalloc(); + data = new byte[size]; + _status = kResStatusAllocated; + errorNum = data ? dec->unpack(file, data, szPacked, size) : SCI_ERROR_RESOURCE_TOO_BIG; + if (errorNum) + unalloc(); delete dec; - return error; + return errorNum; } ResourceCompression ResourceManager::getViewCompression() { @@ -1661,7 +1663,7 @@ ResourceCompression ResourceManager::getViewCompression() { if (!res) continue; - if (res->_source->source_type != kSourceVolume) + if (res->_source->getSourceType() != kSourceVolume) continue; fileStream = getVolumeFile(res->_source); @@ -1673,13 +1675,13 @@ ResourceCompression ResourceManager::getViewCompression() { uint32 szPacked; ResourceCompression compression; - if (readResourceInfo(res, fileStream, szPacked, compression)) { - if (res->_source->resourceFile) + if (res->readResourceInfo(_volVersion, fileStream, szPacked, compression)) { + if (res->_source->_resourceFile) delete fileStream; continue; } - if (res->_source->resourceFile) + if (res->_source->_resourceFile) delete fileStream; if (compression != kCompNone) @@ -1697,6 +1699,10 @@ ViewType ResourceManager::detectViewType() { Resource *res = findResource(ResourceId(kResourceTypeView, i), 0); if (res) { + // Skip views coming from patch files + if (res->_source->getSourceType() == kSourcePatch) + continue; + switch (res->data[1]) { case 128: // If the 2nd byte is 128, it's a VGA game @@ -1752,6 +1758,7 @@ ViewType ResourceManager::detectViewType() { } } + // this may happen if there are serious system issues (or trying to add a broken game) warning("resMan: Couldn't find any views"); return kViewUnknown; } @@ -1862,7 +1869,7 @@ void ResourceManager::detectSciVersion() { } } - warning("Failed to accurately determine SCI version"); + error("Failed to accurately determine SCI version"); // No parser, we assume SCI_VERSION_01. s_sciVersion = SCI_VERSION_01; return; @@ -1911,15 +1918,18 @@ bool ResourceManager::detectHires() { // SCI32 picture uint16 width = READ_LE_UINT16(res->data + 10); uint16 height = READ_LE_UINT16(res->data + 12); + // Surely lowres (e.g. QFG4CD) if ((width == 320) && ((height == 190) || (height == 200))) return false; + // Surely hires if ((width >= 600) || (height >= 400)) return true; } } } - warning("resMan: Couldn't detect hires"); + // We haven't been able to find hires content + return false; #else error("no sci32 support"); @@ -1939,12 +1949,27 @@ bool ResourceManager::detectFontExtended() { return false; } +// detects, if SCI1.1 game uses palette merging or copying - this is supposed to only get used on SCI1.1 games +bool ResourceManager::detectForPaletteMergingForSci11() { + // Load palette 999 (default palette) + Resource *res = findResource(ResourceId(kResourceTypePalette, 999), false); + + if ((res) && (res->size > 30)) { + byte *data = res->data; + // Old palette format used in palette resource? -> it's merging + if ((data[0] == 0 && data[1] == 1) || (data[0] == 0 && data[1] == 0 && READ_LE_UINT16(data + 29) == 0)) + return true; + return false; + } + return false; +} + // Functions below are based on PD code by Brian Provinciano (SCI Studio) bool ResourceManager::hasOldScriptHeader() { Resource *res = findResource(ResourceId(kResourceTypeScript, 0), 0); if (!res) { - warning("resMan: Failed to find script.000"); + error("resMan: Failed to find script.000"); return false; } diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 533c81bdf5..f66b5b3956 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -23,22 +23,23 @@ * */ -#ifndef SCI_SCICORE_RESOURCE_H -#define SCI_SCICORE_RESOURCE_H +#ifndef SCI_RESOURCE_H +#define SCI_RESOURCE_H -#include "common/fs.h" -#include "common/macresman.h" #include "common/str.h" +#include "common/list.h" +#include "common/hashmap.h" #include "sci/graphics/helpers.h" // for ViewType #include "sci/decompressor.h" #include "sci/sci.h" namespace Common { -class ReadStream; -class WriteStream; class File; +class FSList; class FSNode; +class WriteStream; +class SeekableReadStream; } namespace Sci { @@ -73,18 +74,6 @@ enum { MAX_OPENED_VOLUMES = 5 ///< Max number of simultaneously opened volumes }; -enum ResSourceType { - kSourceDirectory = 0, - kSourcePatch, - kSourceVolume, - kSourceExtMap, - kSourceIntMap, - kSourceAudioVolume, - kSourceExtAudioMap, - kSourceWave, - kSourceMacResourceFork -}; - enum ResourceType { kResourceTypeView = 0, kResourceTypePic, @@ -109,6 +98,7 @@ enum ResourceType { kResourceTypeUnknown1, // Translation, currently unsupported kResourceTypeUnknown2, kResourceTypeRobot, + kResourceTypeVMD, kResourceTypeInvalid, // Mac-only resources, these resource types are self-defined @@ -121,152 +111,199 @@ enum ResourceType { const char *getResourceTypeName(ResourceType restype); -class ResourceManager; - -struct ResourceSource { - ResSourceType source_type; - bool scanned; - Common::String location_name; // FIXME: Replace by FSNode ? - const Common::FSNode *resourceFile; - int volume_number; - ResourceSource *associated_map; - uint32 audioCompressionType; - int32 *audioCompressionOffsetMapping; - Common::MacResManager macResMan; +enum ResVersion { + kResVersionUnknown, + kResVersionSci0Sci1Early, + kResVersionSci1Middle, + kResVersionSci1Late, + kResVersionSci11, + kResVersionSci11Mac, + kResVersionSci32 }; +class ResourceManager; +class ResourceSource; + class ResourceId { -public: - ResourceType type; - uint16 number; - uint32 tuple; // Only used for audio36 and sync36 + static inline ResourceType fixupType(ResourceType type) { + if (type < kResourceTypeMacPict || type > kResourceTypeInvalid) + return kResourceTypeInvalid; + return type; + } - ResourceId() : type(kResourceTypeInvalid), number(0), tuple(0) { } + ResourceType _type; + uint16 _number; + uint32 _tuple; // Only used for audio36 and sync36 + +public: + ResourceId() : _type(kResourceTypeInvalid), _number(0), _tuple(0) { } ResourceId(ResourceType type_, uint16 number_, uint32 tuple_ = 0) - : type(type_), number(number_), tuple(tuple_) { - if (type < kResourceTypeMacPict || type > kResourceTypeInvalid) - type = kResourceTypeInvalid; + : _type(fixupType(type_)), _number(number_), _tuple(tuple_) { } ResourceId(ResourceType type_, uint16 number_, byte noun, byte verb, byte cond, byte seq) - : type(type_), number(number_) { - tuple = (noun << 24) | (verb << 16) | (cond << 8) | seq; - - if ((type < kResourceTypeView) || (type > kResourceTypeInvalid)) - type = kResourceTypeInvalid; + : _type(fixupType(type_)), _number(number_) { + _tuple = (noun << 24) | (verb << 16) | (cond << 8) | seq; } - Common::String toString() { + Common::String toString() const { char buf[32]; - snprintf(buf, 32, "%s.%i", getResourceTypeName(type), number); + snprintf(buf, 32, "%s.%i", getResourceTypeName(_type), _number); Common::String retStr = buf; - if (tuple != 0) { - snprintf(buf, 32, "(%i, %i, %i, %i)", tuple >> 24, (tuple >> 16) & 0xff, (tuple >> 8) & 0xff, tuple & 0xff); + if (_tuple != 0) { + snprintf(buf, 32, "(%i, %i, %i, %i)", _tuple >> 24, (_tuple >> 16) & 0xff, (_tuple >> 8) & 0xff, _tuple & 0xff); retStr += buf; } return retStr; } -}; -struct ResourceIdHash : public Common::UnaryFunction<ResourceId, uint> { - uint operator()(ResourceId val) const { return ((uint)((val.type << 16) | val.number)) ^ val.tuple; } -}; + inline ResourceType getType() const { return _type; } + inline uint16 getNumber() const { return _number; } + inline uint32 getTuple() const { return _tuple; } -struct ResourceIdEqualTo : public Common::BinaryFunction<ResourceId, ResourceId, bool> { - bool operator()(const ResourceId &x, const ResourceId &y) const { return (x.type == y.type) && (x.number == y.number) && (x.tuple == y.tuple); } -}; + inline uint hash() const { + return ((uint)((_type << 16) | _number)) ^ _tuple; + } -struct ResourceIdLess : public Common::BinaryFunction<ResourceId, ResourceId, bool> { - bool operator()(const ResourceId &x, const ResourceId &y) const { - return (x.type < y.type) || ((x.type == y.type) && (x.number < y.number)) - || ((x.type == y.type) && (x.number == y.number) && (x.tuple < y.tuple)); + bool operator==(const ResourceId &other) const { + return (_type == other._type) && (_number == other._number) && (_tuple == other._tuple); + } + + bool operator<(const ResourceId &other) const { + return (_type < other._type) || ((_type == other._type) && (_number < other._number)) + || ((_type == other._type) && (_number == other._number) && (_tuple < other._tuple)); } }; +struct ResourceIdHash : public Common::UnaryFunction<ResourceId, uint> { + uint operator()(ResourceId val) const { return val.hash(); } +}; + /** Class for storing resources in memory */ class Resource { friend class ResourceManager; -public: - Resource(); - ~Resource(); - void unalloc(); -// NOTE : Currently all member data has the same name and public visibility -// to let the rest of the engine compile without changes + // FIXME: These 'friend' declarations are meant to be a temporary hack to + // ease transition to the ResourceSource class system. + friend class ResourceSource; + friend class PatchResourceSource; + friend class WaveResourceSource; + friend class AudioVolumeResourceSource; + friend class MacResourceForkResourceSource; + +// NOTE : Currently most member variables lack the underscore prefix and have +// public visibility to let the rest of the engine compile without changes. public: - ResourceId _id; byte *data; uint32 size; byte *_header; uint32 _headerSize; +public: + Resource(ResourceId id); + ~Resource(); + void unalloc(); + + inline ResourceType getType() const { return _id.getType(); } + inline uint16 getNumber() const { return _id.getNumber(); } + bool isLocked() const { return _status == kResStatusLocked; } + /** + * Write the resource to the specified stream. + * This method is used only by the "dump" debugger command. + */ void writeToStream(Common::WriteStream *stream) const; - uint32 getAudioCompressionType(); + + // FIXME: This audio specific method is a hack. After all, why should a + // Resource have audio specific methods? But for now we keep this, as it + // eases transition. + uint32 getAudioCompressionType() const; protected: + ResourceId _id; // TODO: _id could almost be made const, only readResourceInfo() modifies it... int32 _fileOffset; /**< Offset in file */ ResourceStatus _status; uint16 _lockers; /**< Number of places where this resource was locked */ ResourceSource *_source; + + bool loadPatch(Common::SeekableReadStream *file); + bool loadFromPatchFile(); + bool loadFromWaveFile(Common::SeekableReadStream *file); + bool loadFromAudioVolumeSCI1(Common::SeekableReadStream *file); + bool loadFromAudioVolumeSCI11(Common::SeekableReadStream *file); + int decompress(ResVersion volVersion, Common::SeekableReadStream *file); + int readResourceInfo(ResVersion volVersion, Common::SeekableReadStream *file, uint32 &szPacked, ResourceCompression &compression); }; -typedef Common::HashMap<ResourceId, Resource *, ResourceIdHash, ResourceIdEqualTo> ResourceMap; +typedef Common::HashMap<ResourceId, Resource *, ResourceIdHash> ResourceMap; class ResourceManager { -public: - enum ResVersion { - kResVersionUnknown, - kResVersionSci0Sci1Early, - kResVersionSci1Middle, - kResVersionSci1Late, - kResVersionSci11, - kResVersionSci11Mac, - kResVersionSci32 - }; + // FIXME: These 'friend' declarations are meant to be a temporary hack to + // ease transition to the ResourceSource class system. + friend class ResourceSource; + friend class DirectoryResourceSource; + friend class PatchResourceSource; + friend class ExtMapResourceSource; + friend class IntMapResourceSource; + friend class AudioVolumeResourceSource; + friend class ExtAudioMapResourceSource; + friend class WaveResourceSource; + friend class MacResourceForkResourceSource; +public: /** * Creates a new SCI resource manager. */ ResourceManager(); - ResourceManager(const Common::FSList &fslist); ~ResourceManager(); + + /** + * Initializes the resource manager. + */ + void init(); + + int addAppropriateSources(); + int addAppropriateSources(const Common::FSList &fslist); // TODO: Switch from FSList to Common::Archive? + /** * Looks up a resource's data. - * @param id: The resource type to look for - * @param lock: non-zero iff the resource should be locked - * @return (Resource *): The resource, or NULL if it doesn't exist + * @param id The resource type to look for + * @param lock non-zero iff the resource should be locked + * @return The resource, or NULL if it doesn't exist * @note Locked resources are guaranteed not to have their contents freed until * they are unlocked explicitly (by unlockResource). */ Resource *findResource(ResourceId id, bool lock); - /* Unlocks a previously locked resource - ** (Resource *) res: The resource to free - ** Returns : () - */ + /** + * Unlocks a previously locked resource. + * @param res The resource to free + */ void unlockResource(Resource *res); - /* Tests whether a resource exists - ** (ResourceId) id: Id of the resource to check - ** Returns : (Resource *) non-NULL if the resource exists, NULL otherwise - ** This function may often be much faster than finding the resource - ** and should be preferred for simple tests. - ** The resource object returned is, indeed, the resource in question, but - ** it should be used with care, as it may be unallocated. - ** Use scir_find_resource() if you want to use the data contained in the resource. - */ + /** + * Tests whether a resource exists. + * + * This function may often be much faster than finding the resource + * and should be preferred for simple tests. + * The resource object returned is, indeed, the resource in question, but + * it should be used with care, as it may be unallocated. + * Use scir_find_resource() if you want to use the data contained in the resource. + * + * @param id Id of the resource to check + * @return non-NULL if the resource exists, NULL otherwise + */ Resource *testResource(ResourceId id); /** * Returns a list of all resources of the specified type. - * @param type: The resource type to look for - * @param mapNumber: For audio36 and sync36, limit search to this map - * @return: The resource list + * @param type The resource type to look for + * @param mapNumber For audio36 and sync36, limit search to this map + * @return The resource list */ Common::List<ResourceId> *listResources(ResourceType type, int mapNumber = -1); @@ -278,27 +315,30 @@ public: ViewType getViewType() const { return _viewType; } const char *getMapVersionDesc() const { return versionDescription(_mapVersion); } const char *getVolVersionDesc() const { return versionDescription(_volVersion); } + ResVersion getVolVersion() const { return _volVersion; } /** * Adds the appropriate GM patch from the Sierra MIDI utility as 4.pat, without * requiring the user to rename the file to 4.pat. Thus, the original Sierra * archive can be extracted in the extras directory, and the GM patches can be - * applied per game, if applicable + * applied per game, if applicable. */ - void addNewGMPatch(const Common::String &gameId); + void addNewGMPatch(SciGameId gameId); bool detectHires(); // Detects, if standard font of current game includes extended characters (>0x80) bool detectFontExtended(); + // Detects, if SCI1.1 game uses palette merging + bool detectForPaletteMergingForSci11(); /** - * Finds the internal Sierra ID of the current game from script 0 + * Finds the internal Sierra ID of the current game from script 0. */ Common::String findSierraGameId(); /** - * Finds the location of the game object from script 0 - * @param addSci11ScriptOffset: Adjust the return value for SCI1.1 and newer + * Finds the location of the game object from script 0. + * @param addSci11ScriptOffset Adjust the return value for SCI1.1 and newer * games. Needs to be false when the heap is accessed directly inside * findSierraGameId(). */ @@ -325,85 +365,54 @@ protected: ResVersion _mapVersion; ///< resource.map version /** - * Initializes the resource manager - */ - void init(); - - /** * Add a path to the resource manager's list of sources. * @return a pointer to the added source structure, or NULL if an error occurred. */ - ResourceSource *addPatchDir(const char *path); + ResourceSource *addPatchDir(const Common::String &path); - ResourceSource *getVolume(ResourceSource *map, int volume_nr); + ResourceSource *findVolume(ResourceSource *map, int volume_nr); /** * Adds a source to the resource manager's list of sources. - * @param map The map associated with this source - * @param type The source type - * @param filename The name of the source to add - * @return A pointer to the added source structure, or NULL if an error occurred. + * @param source The new source to add + * @return A pointer to the added source structure, or NULL if an error occurred. */ - ResourceSource *addSource(ResourceSource *map, ResSourceType type, const char *filename, - int number); - - ResourceSource *addSource(ResourceSource *map, ResSourceType type, - const Common::FSNode *resFile, int number); + ResourceSource *addSource(ResourceSource *source); /** - * Add an external (i.e., separate file) map resource to the resource manager's list of sources. - * @param file_name The name of the volume to add + * Add an external (i.e., separate file) map resource to the resource + * manager's list of sources. + * @param filename The name of the volume to add * @param volume_nr The volume number the map starts at, 0 for <SCI2.1 * @return A pointer to the added source structure, or NULL if an error occurred. */ - ResourceSource *addExternalMap(const char *file_name, int volume_nr = 0); + ResourceSource *addExternalMap(const Common::String &filename, int volume_nr = 0); ResourceSource *addExternalMap(const Common::FSNode *mapFile, int volume_nr = 0); /** - * Add an internal (i.e., resource) map to the resource manager's list of sources. - * @param name The name of the resource to add - * @param resNr The map resource number - * @return A pointer to the added source structure, or NULL if an error occurred. - */ - ResourceSource *addInternalMap(const char *name, int resNr); - - /** - * Checks, if an audio volume got compressed by our tool. If that's the case, it will set audioCompressionType - * and read in the offset translation table for later usage. - */ - void checkIfAudioVolumeIsCompressed(ResourceSource *source); - - /** * Scans newly registered resource sources for resources, earliest addition first. - * @param detected_version: Pointer to the detected version number, + * @param detected_version Pointer to the detected version number, * used during startup. May be NULL. * @return One of SCI_ERROR_*. */ void scanNewSources(); - int addAppropriateSources(); - int addAppropriateSources(const Common::FSList &fslist); + int addInternalSources(); void freeResourceSources(); /** - * Returns a string describing a ResVersion - * @param version: The resource version - * @return: The description of version + * Returns a string describing a ResVersion. + * @param version The resource version + * @return The description of version */ const char *versionDescription(ResVersion version) const; Common::SeekableReadStream *getVolumeFile(ResourceSource *source); void loadResource(Resource *res); - bool loadPatch(Resource *res, Common::SeekableReadStream *file); - bool loadFromPatchFile(Resource *res); - bool loadFromWaveFile(Resource *res, Common::SeekableReadStream *file); - bool loadFromAudioVolumeSCI1(Resource *res, Common::SeekableReadStream *file); - bool loadFromAudioVolumeSCI11(Resource *res, Common::SeekableReadStream *file); void freeOldResources(); - int decompress(Resource *res, Common::SeekableReadStream *file); - int readResourceInfo(Resource *res, Common::SeekableReadStream *file, uint32&szPacked, ResourceCompression &compression); void addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size = 0); + Resource *updateResource(ResourceId resId, ResourceSource *src, uint32 size); void removeAudioResource(ResourceId resId); /**--- Resource map decoding functions ---*/ @@ -423,23 +432,16 @@ protected: * @return 0 on success, an SCI_ERROR_* code otherwise */ int readResourceMapSCI1(ResourceSource *map); - - /** - * Reads the SCI1.1+ resource file from a Mac resource fork. - * @param source The source - * @return 0 on success, an SCI_ERROR_* code otherwise - */ - int readMacResourceFork(ResourceSource *source); /** - * Reads SCI1.1 audio map resources + * Reads SCI1.1 audio map resources. * @param map The map * @return 0 on success, an SCI_ERROR_* code otherwise */ int readAudioMapSCI11(ResourceSource *map); /** - * Reads SCI1 audio map files + * Reads SCI1 audio map files. * @param map The map * @param unload Unload the map instead of loading it * @return 0 on success, an SCI_ERROR_* code otherwise @@ -451,16 +453,15 @@ protected: /** * Reads patch files from a local directory. */ - void readResourcePatches(ResourceSource *source); -#ifdef ENABLE_SCI32 - void readResourcePatchesBase36(ResourceSource *source); -#endif + void readResourcePatches(); + void readResourcePatchesBase36(); void processPatch(ResourceSource *source, ResourceType resourceType, uint16 resourceNr, uint32 tuple = 0); /** - * Process wave files as patches for Audio resources + * Process wave files as patches for Audio resources. */ void readWaveAudioPatches(); + void processWavePatch(ResourceId resourceId, Common::String name); /** * Applies to all versions before 0.000.395 (i.e. KQ4 old, XMAS 1988 and LSL2). @@ -491,6 +492,7 @@ public: uint16 prio; uint16 size; byte *data; + uint16 curPos; long time; byte prev; }; @@ -515,7 +517,6 @@ public: Track *getDigitalTrack(); int getChannelFilterMask(int hardwareMask, bool wantsRhythm); byte getInitialVoiceCount(byte channel); - bool isChannelUsed(byte channel) const { return _channelsUsed & (1 << channel); } private: SciVersion _soundVersion; @@ -523,11 +524,8 @@ private: Track *_tracks; Resource *_innerResource; ResourceManager *_resMan; - uint16 _channelsUsed; - - void setChannelUsed(byte channel) { _channelsUsed |= (1 << channel); } }; } // End of namespace Sci -#endif // SCI_SCICORE_RESOURCE_H +#endif // SCI_RESOURCE_H diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 57efbdcb38..13aa81cb24 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -25,20 +25,30 @@ // Resource library +#include "common/archive.h" #include "common/file.h" #include "sci/resource.h" +#include "sci/resource_intern.h" #include "sci/util.h" namespace Sci { -void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) { - Common::SeekableReadStream *fileStream = getVolumeFile(source); +AudioVolumeResourceSource::AudioVolumeResourceSource(ResourceManager *resMan, const Common::String &name, ResourceSource *map, int volNum) + : VolumeResourceSource(name, map, volNum, kSourceAudioVolume) { - if (!fileStream) { - warning("Failed to open %s", source->location_name.c_str()); + _audioCompressionType = 0; + _audioCompressionOffsetMapping = NULL; + + /* + * Check if this audio volume got compressed by our tool. If that is the + * case, set _audioCompressionType and read in the offset translation + * table for later usage. + */ + + Common::SeekableReadStream *fileStream = getVolumeFile(resMan, 0); + if (!fileStream) return; - } fileStream->seek(0, SEEK_SET); uint32 compressionType = fileStream->readUint32BE(); @@ -47,13 +57,13 @@ void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) { case MKID_BE('OGG '): case MKID_BE('FLAC'): // Detected a compressed audio volume - source->audioCompressionType = compressionType; + _audioCompressionType = compressionType; // Now read the whole offset mapping table for later usage int32 recordCount = fileStream->readUint32LE(); if (!recordCount) error("compressed audio volume doesn't contain any entries!"); int32 *offsetMapping = new int32[(recordCount + 1) * 2]; - source->audioCompressionOffsetMapping = offsetMapping; + _audioCompressionOffsetMapping = offsetMapping; for (int recordNo = 0; recordNo < recordCount; recordNo++) { *offsetMapping++ = fileStream->readUint32LE(); *offsetMapping++ = fileStream->readUint32LE(); @@ -63,105 +73,124 @@ void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) { *offsetMapping++ = fileStream->size(); } - if (source->resourceFile) + if (_resourceFile) delete fileStream; } -bool ResourceManager::loadFromWaveFile(Resource *res, Common::SeekableReadStream *file) { - res->data = new byte[res->size]; +bool Resource::loadFromWaveFile(Common::SeekableReadStream *file) { + data = new byte[size]; - uint32 really_read = file->read(res->data, res->size); - if (really_read != res->size) - error("Read %d bytes from %s but expected %d", really_read, res->_id.toString().c_str(), res->size); + uint32 really_read = file->read(data, size); + if (really_read != size) + error("Read %d bytes from %s but expected %d", really_read, _id.toString().c_str(), size); - res->_status = kResStatusAllocated; + _status = kResStatusAllocated; return true; } -bool ResourceManager::loadFromAudioVolumeSCI11(Resource *res, Common::SeekableReadStream *file) { +bool Resource::loadFromAudioVolumeSCI11(Common::SeekableReadStream *file) { // Check for WAVE files here uint32 riffTag = file->readUint32BE(); if (riffTag == MKID_BE('RIFF')) { - res->_headerSize = 0; - res->size = file->readUint32LE(); + _headerSize = 0; + size = file->readUint32LE(); file->seek(-8, SEEK_CUR); - return loadFromWaveFile(res, file); + return loadFromWaveFile(file); } file->seek(-4, SEEK_CUR); ResourceType type = (ResourceType)(file->readByte() & 0x7f); - if (((res->_id.type == kResourceTypeAudio || res->_id.type == kResourceTypeAudio36) && (type != kResourceTypeAudio)) - || ((res->_id.type == kResourceTypeSync || res->_id.type == kResourceTypeSync36) && (type != kResourceTypeSync))) { - warning("Resource type mismatch loading %s", res->_id.toString().c_str()); - res->unalloc(); + if (((getType() == kResourceTypeAudio || getType() == kResourceTypeAudio36) && (type != kResourceTypeAudio)) + || ((getType() == kResourceTypeSync || getType() == kResourceTypeSync36) && (type != kResourceTypeSync))) { + warning("Resource type mismatch loading %s", _id.toString().c_str()); + unalloc(); return false; } - res->_headerSize = file->readByte(); + _headerSize = file->readByte(); if (type == kResourceTypeAudio) { - if (res->_headerSize != 11 && res->_headerSize != 12) { + if (_headerSize != 7 && _headerSize != 11 && _headerSize != 12) { warning("Unsupported audio header"); - res->unalloc(); + unalloc(); return false; } - // Load sample size - file->seek(7, SEEK_CUR); - res->size = file->readUint32LE(); - // Adjust offset to point at the header data again - file->seek(-11, SEEK_CUR); + if (_headerSize != 7) { // Size is defined already from the map + // Load sample size + file->seek(7, SEEK_CUR); + size = file->readUint32LE(); + // Adjust offset to point at the header data again + file->seek(-11, SEEK_CUR); + } } - return loadPatch(res, file); + return loadPatch(file); } -bool ResourceManager::loadFromAudioVolumeSCI1(Resource *res, Common::SeekableReadStream *file) { - res->data = new byte[res->size]; +bool Resource::loadFromAudioVolumeSCI1(Common::SeekableReadStream *file) { + data = new byte[size]; - if (res->data == NULL) { - error("Can't allocate %d bytes needed for loading %s", res->size, res->_id.toString().c_str()); + if (data == NULL) { + error("Can't allocate %d bytes needed for loading %s", size, _id.toString().c_str()); } - unsigned int really_read = file->read(res->data, res->size); - if (really_read != res->size) - warning("Read %d bytes from %s but expected %d", really_read, res->_id.toString().c_str(), res->size); + unsigned int really_read = file->read(data, size); + if (really_read != size) + warning("Read %d bytes from %s but expected %d", really_read, _id.toString().c_str(), size); - res->_status = kResStatusAllocated; + _status = kResStatusAllocated; return true; } -void ResourceManager::addNewGMPatch(const Common::String &gameId) { +void ResourceManager::addNewGMPatch(SciGameId gameId) { Common::String gmPatchFile; - if (gameId == "ecoquest") + switch (gameId) { + case GID_ECOQUEST: gmPatchFile = "ECO1GM.PAT"; - else if (gameId == "hoyle3") - gmPatchFile = "HOY3GM.PAT"; - else if (gameId == "hoyle3") + break; + case GID_HOYLE3: gmPatchFile = "HOY3GM.PAT"; - else if (gameId == "lsl1sci") + break; + case GID_LSL1: gmPatchFile = "LL1_GM.PAT"; - else if (gameId == "lsl5") + break; + case GID_LSL5: gmPatchFile = "LL5_GM.PAT"; - else if (gameId == "longbow") + break; + case GID_LONGBOW: gmPatchFile = "ROBNGM.PAT"; - else if (gameId == "sq1sci") + break; + case GID_SQ1: gmPatchFile = "SQ1_GM.PAT"; - else if (gameId == "sq4") + break; + case GID_SQ4: gmPatchFile = "SQ4_GM.PAT"; - else if (gameId == "fairytales") + break; + case GID_FAIRYTALES: gmPatchFile = "TALEGM.PAT"; + break; + default: + break; + } if (!gmPatchFile.empty() && Common::File::exists(gmPatchFile)) { - ResourceSource *psrcPatch = new ResourceSource; - psrcPatch->source_type = kSourcePatch; - psrcPatch->resourceFile = 0; - psrcPatch->location_name = gmPatchFile; + ResourceSource *psrcPatch = new PatchResourceSource(gmPatchFile); processPatch(psrcPatch, kResourceTypePatch, 4); } } +void ResourceManager::processWavePatch(ResourceId resourceId, Common::String name) { + ResourceSource *resSrc = new WaveResourceSource(name); + Common::File file; + file.open(name); + + updateResource(resourceId, resSrc, file.size()); + + debugC(1, kDebugLevelResMan, "Patching %s - OK", name.c_str()); +} + void ResourceManager::readWaveAudioPatches() { // Here we do check for SCI1.1+ so we can patch wav files in as audio resources Common::ArchiveMemberList files; @@ -170,39 +199,8 @@ void ResourceManager::readWaveAudioPatches() { for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { Common::String name = (*x)->getName(); - if (isdigit(name[0])) { - int number = atoi(name.c_str()); - ResourceSource *psrcPatch = new ResourceSource; - psrcPatch->source_type = kSourceWave; - psrcPatch->resourceFile = 0; - psrcPatch->location_name = name; - psrcPatch->volume_number = 0; - psrcPatch->audioCompressionType = 0; - - ResourceId resId = ResourceId(kResourceTypeAudio, number); - - Resource *newrsc = NULL; - - // Prepare destination, if neccessary - if (_resMap.contains(resId) == false) { - newrsc = new Resource; - _resMap.setVal(resId, newrsc); - } else - newrsc = _resMap.getVal(resId); - - // Get the size of the file - Common::SeekableReadStream *stream = (*x)->createReadStream(); - uint32 fileSize = stream->size(); - delete stream; - - // Overwrite everything, because we're patching - newrsc->_id = resId; - newrsc->_status = kResStatusNoMalloc; - newrsc->_source = psrcPatch; - newrsc->size = fileSize; - newrsc->_headerSize = 0; - debugC(1, kDebugLevelResMan, "Patching %s - OK", psrcPatch->location_name.c_str()); - } + if (isdigit(name[0])) + processWavePatch(ResourceId(kResourceTypeAudio, atoi(name.c_str())), name); } } @@ -211,7 +209,7 @@ void ResourceManager::removeAudioResource(ResourceId resId) { if (_resMap.contains(resId)) { Resource *res = _resMap.getVal(resId); - if (res->_source->source_type == kSourceAudioVolume) { + if (res->_source->getSourceType() == kSourceAudioVolume) { if (res->_status == kResStatusLocked) { warning("Failed to remove resource %s (still in use)", resId.toString().c_str()); } else { @@ -261,27 +259,31 @@ void ResourceManager::removeAudioResource(ResourceId resId) { // w syncAscSize (iff seq has bit 6 set) int ResourceManager::readAudioMapSCI11(ResourceSource *map) { - bool isEarly = true; uint32 offset = 0; - Resource *mapRes = findResource(ResourceId(kResourceTypeMap, map->volume_number), false); + Resource *mapRes = findResource(ResourceId(kResourceTypeMap, map->_volumeNumber), false); if (!mapRes) { - warning("Failed to open %i.MAP", map->volume_number); + warning("Failed to open %i.MAP", map->_volumeNumber); return SCI_ERROR_RESMAP_NOT_FOUND; } - ResourceSource *src = getVolume(map, 0); + ResourceSource *src = findVolume(map, 0); if (!src) return SCI_ERROR_NO_RESOURCE_FILES_FOUND; byte *ptr = mapRes->data; - if (map->volume_number == 65535) { - // Heuristic to detect late SCI1.1 map format - if ((mapRes->size >= 6) && (ptr[mapRes->size - 6] != 0xff)) - isEarly = false; + // Heuristic to detect entry size + uint32 entrySize = 0; + for (int i = mapRes->size - 1; i >= 0; --i) { + if (ptr[i] == 0xff) + entrySize++; + else + break; + } + if (map->_volumeNumber == 65535) { while (ptr < mapRes->data + mapRes->size) { uint16 n = READ_LE_UINT16(ptr); ptr += 2; @@ -289,7 +291,7 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { if (n == 0xffff) break; - if (isEarly) { + if (entrySize == 6) { offset = READ_LE_UINT32(ptr); ptr += 4; } else { @@ -299,10 +301,25 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { addResource(ResourceId(kResourceTypeAudio, n), src, offset); } + } else if (map->_volumeNumber == 0 && entrySize == 10 && ptr[3] == 0) { + // QFG3 demo format + // ptr[3] would be 'seq' in the normal format and cannot possibly be 0 + while (ptr < mapRes->data + mapRes->size) { + uint16 n = READ_BE_UINT16(ptr); + ptr += 2; + + if (n == 0xffff) + break; + + offset = READ_LE_UINT32(ptr); + ptr += 4; + uint32 size = READ_LE_UINT32(ptr); + ptr += 4; + + addResource(ResourceId(kResourceTypeAudio, n), src, offset, size); + } } else { - // Heuristic to detect late SCI1.1 map format - if ((mapRes->size >= 11) && (ptr[mapRes->size - 11] == 0xff)) - isEarly = false; + bool isEarly = (entrySize != 11); if (!isEarly) { offset = READ_LE_UINT32(ptr); @@ -330,15 +347,17 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { ptr += 2; if (syncSize > 0) - addResource(ResourceId(kResourceTypeSync36, map->volume_number, n & 0xffffff3f), src, offset, syncSize); + addResource(ResourceId(kResourceTypeSync36, map->_volumeNumber, n & 0xffffff3f), src, offset, syncSize); } if (n & 0x40) { + // This seems to define the size of raw lipsync data (at least + // in kq6), may also just be general appended data. syncSize += READ_LE_UINT16(ptr); ptr += 2; } - addResource(ResourceId(kResourceTypeAudio36, map->volume_number, n & 0xffffff3f), src, offset + syncSize); + addResource(ResourceId(kResourceTypeAudio36, map->_volumeNumber, n & 0xffffff3f), src, offset + syncSize); } } @@ -358,7 +377,7 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) { Common::File file; - if (!file.open(map->location_name)) + if (!file.open(map->getLocationName())) return SCI_ERROR_RESMAP_NOT_FOUND; bool oldFormat = (file.readUint16LE() >> 11) == kResourceTypeAudio; @@ -370,7 +389,7 @@ int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) { uint32 size = file.readUint32LE(); if (file.eos() || file.err()) { - warning("Error while reading %s", map->location_name.c_str()); + warning("Error while reading %s", map->getLocationName().c_str()); return SCI_ERROR_RESMAP_NOT_FOUND; } @@ -388,7 +407,7 @@ int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) { offset &= 0x0fffffff; // least significant 28 bits } - ResourceSource *src = getVolume(map, volume_nr); + ResourceSource *src = findVolume(map, volume_nr); if (src) { if (unload) @@ -405,7 +424,7 @@ int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) { void ResourceManager::setAudioLanguage(int language) { if (_audioMapSCI1) { - if (_audioMapSCI1->volume_number == language) { + if (_audioMapSCI1->_volumeNumber == language) { // This language is already loaded return; } @@ -417,7 +436,7 @@ void ResourceManager::setAudioLanguage(int language) { Common::List<ResourceSource *>::iterator it = _sources.begin(); while (it != _sources.end()) { ResourceSource *src = *it; - if (src->associated_map == _audioMapSCI1) { + if (src->findVolume(_audioMapSCI1, src->_volumeNumber)) { it = _sources.erase(it); delete src; } else { @@ -441,7 +460,7 @@ void ResourceManager::setAudioLanguage(int language) { return; } - _audioMapSCI1 = addSource(NULL, kSourceExtAudioMap, fullname.c_str(), language); + _audioMapSCI1 = addSource(new ExtAudioMapResourceSource(fullname, language)); // Search for audio volumes for this language and add them to the source list Common::ArchiveMemberList files; @@ -451,18 +470,18 @@ void ResourceManager::setAudioLanguage(int language) { const char *dot = strrchr(name.c_str(), '.'); int number = atoi(dot + 1); - addSource(_audioMapSCI1, kSourceAudioVolume, name.c_str(), number); + addSource(new AudioVolumeResourceSource(this, name, _audioMapSCI1, number)); } scanNewSources(); } int ResourceManager::getAudioLanguage() const { - return (_audioMapSCI1 ? _audioMapSCI1->volume_number : 0); + return (_audioMapSCI1 ? _audioMapSCI1->_volumeNumber : 0); } -SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersion soundVersion) : _resMan(resMan), _soundVersion(soundVersion) { - Resource *resource = _resMan->findResource(ResourceId(kResourceTypeSound, resNumber), true); +SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVersion soundVersion) : _resMan(resMan), _soundVersion(soundVersion) { + Resource *resource = _resMan->findResource(ResourceId(kResourceTypeSound, resourceNr), true); int trackNr, channelNr; if (!resource) return; @@ -473,8 +492,6 @@ SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersi byte *dataEnd; Channel *channel, *sampleChannel; - _channelsUsed = 0; - switch (_soundVersion) { case SCI_VERSION_0_EARLY: case SCI_VERSION_0_LATE: @@ -537,6 +554,9 @@ SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersi } _tracks = new Track[_trackCount]; data = resource->data; + + byte channelCount; + for (trackNr = 0; trackNr < _trackCount; trackNr++) { // Track info starts with track type:BYTE // Then the channel information gets appended Unknown:WORD, ChannelOffset:WORD, ChannelSize:WORD @@ -546,35 +566,47 @@ SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersi _tracks[trackNr].type = *data++; // Counting # of channels used data2 = data; - _tracks[trackNr].channelCount = 0; + channelCount = 0; while (*data2 != 0xFF) { data2 += 6; + channelCount++; _tracks[trackNr].channelCount++; } - _tracks[trackNr].channels = new Channel[_tracks[trackNr].channelCount]; + _tracks[trackNr].channels = new Channel[channelCount]; + _tracks[trackNr].channelCount = 0; _tracks[trackNr].digitalChannelNr = -1; // No digital sound associated _tracks[trackNr].digitalSampleRate = 0; _tracks[trackNr].digitalSampleSize = 0; _tracks[trackNr].digitalSampleStart = 0; _tracks[trackNr].digitalSampleEnd = 0; if (_tracks[trackNr].type != 0xF0) { // Digital track marker - not supported currently - for (channelNr = 0; channelNr < _tracks[trackNr].channelCount; channelNr++) { + channelNr = 0; + while (channelCount--) { channel = &_tracks[trackNr].channels[channelNr]; channel->prio = READ_LE_UINT16(data); - channel->data = resource->data + READ_LE_UINT16(data + 2) + 2; - channel->size = READ_LE_UINT16(data + 4) - 2; // Not counting channel header - channel->number = *(channel->data - 2); - setChannelUsed(channel->number); - channel->poly = *(channel->data - 1); - channel->time = channel->prev = 0; - if (channel->number == 0xFE) { // Digital channel - _tracks[trackNr].digitalChannelNr = channelNr; - _tracks[trackNr].digitalSampleRate = READ_LE_UINT16(channel->data); - _tracks[trackNr].digitalSampleSize = READ_LE_UINT16(channel->data + 2); - _tracks[trackNr].digitalSampleStart = READ_LE_UINT16(channel->data + 4); - _tracks[trackNr].digitalSampleEnd = READ_LE_UINT16(channel->data + 6); - channel->data += 8; // Skip over header - channel->size -= 8; + uint dataOffset = READ_LE_UINT16(data + 2); + if (dataOffset < resource->size) { + channel->data = resource->data + dataOffset; + channel->size = READ_LE_UINT16(data + 4); + channel->curPos = 0; + channel->number = *channel->data; + channel->poly = *(channel->data + 1); + channel->time = channel->prev = 0; + channel->data += 2; // skip over header + channel->size -= 2; // remove header size + if (channel->number == 0xFE) { // Digital channel + _tracks[trackNr].digitalChannelNr = channelNr; + _tracks[trackNr].digitalSampleRate = READ_LE_UINT16(channel->data); + _tracks[trackNr].digitalSampleSize = READ_LE_UINT16(channel->data + 2); + _tracks[trackNr].digitalSampleStart = READ_LE_UINT16(channel->data + 4); + _tracks[trackNr].digitalSampleEnd = READ_LE_UINT16(channel->data + 6); + channel->data += 8; // Skip over header + channel->size -= 8; + } + _tracks[trackNr].channelCount++; + channelNr++; + } else { + warning("Invalid offset inside sound resource %d: track %d, channel %d", resourceNr, trackNr, channelNr); } data += 6; } diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h new file mode 100644 index 0000000000..45421dd722 --- /dev/null +++ b/engines/sci/resource_intern.h @@ -0,0 +1,193 @@ +/* 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 SCI_RESOURCE_INTERN_H +#define SCI_RESOURCE_INTERN_H + +#include "sci/resource.h" + +namespace Common { + class MacResManager; +} + +namespace Sci { + +enum ResSourceType { + kSourceDirectory = 0, + kSourcePatch, + kSourceVolume, + kSourceExtMap, + kSourceIntMap, + kSourceAudioVolume, + kSourceExtAudioMap, + kSourceWave, + kSourceMacResourceFork +}; + + +class ResourceSource { +protected: + const ResSourceType _sourceType; + const Common::String _name; + +public: + bool _scanned; + const Common::FSNode * const _resourceFile; + const int _volumeNumber; + +protected: + ResourceSource(ResSourceType type, const Common::String &name, int volNum = 0, const Common::FSNode *resFile = 0); +public: + virtual ~ResourceSource(); + + ResSourceType getSourceType() const { return _sourceType; } + const Common::String &getLocationName() const { return _name; } + + // Auxiliary method, used by loadResource implementations. + Common::SeekableReadStream *getVolumeFile(ResourceManager *resMan, Resource *res); + + /** + * TODO: Document this + */ + virtual ResourceSource *findVolume(ResourceSource *map, int volNum) { + return NULL; + }; + + /** + * Scan this source for TODO. + */ + virtual void scanSource(ResourceManager *resMan) {} + + /** + * Load a resource. + */ + virtual void loadResource(ResourceManager *resMan, Resource *res); + + // FIXME: This audio specific method is a hack. After all, why should a + // ResourceSource or a Resource (which uses this method) have audio + // specific methods? But for now we keep this, as it eases transition. + virtual uint32 getAudioCompressionType() const { return 0; } +}; + +class DirectoryResourceSource : public ResourceSource { +public: + DirectoryResourceSource(const Common::String &name) : ResourceSource(kSourceDirectory, name) {} + + virtual void scanSource(ResourceManager *resMan); +}; + +class PatchResourceSource : public ResourceSource { +public: + PatchResourceSource(const Common::String &name) : ResourceSource(kSourcePatch, name) {} + + virtual void loadResource(ResourceManager *resMan, Resource *res); +}; + +class VolumeResourceSource : public ResourceSource { +protected: + ResourceSource * const _associatedMap; + +public: + VolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum, ResSourceType type = kSourceVolume) + : ResourceSource(type, name, volNum), _associatedMap(map) { + } + + VolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum, const Common::FSNode *resFile) + : ResourceSource(kSourceVolume, name, volNum, resFile), _associatedMap(map) { + } + + virtual ResourceSource *findVolume(ResourceSource *map, int volNum) { + if (_associatedMap == map && _volumeNumber == volNum) + return this; + return NULL; + }; +}; + +class ExtMapResourceSource : public ResourceSource { +public: + ExtMapResourceSource(const Common::String &name, int volNum, const Common::FSNode *resFile = 0) + : ResourceSource(kSourceExtMap, name, volNum, resFile) { + } + + virtual void scanSource(ResourceManager *resMan); +}; + +class IntMapResourceSource : public ResourceSource { +public: + IntMapResourceSource(const Common::String &name, int volNum) + : ResourceSource(kSourceIntMap, name, volNum) { + } + + virtual void scanSource(ResourceManager *resMan); +}; + +class AudioVolumeResourceSource : public VolumeResourceSource { +protected: + uint32 _audioCompressionType; + int32 *_audioCompressionOffsetMapping; + +public: + AudioVolumeResourceSource(ResourceManager *resMan, const Common::String &name, ResourceSource *map, int volNum); + + virtual void loadResource(ResourceManager *resMan, Resource *res); + + virtual uint32 getAudioCompressionType() const; +}; + +class ExtAudioMapResourceSource : public ResourceSource { +public: + ExtAudioMapResourceSource(const Common::String &name, int volNum) + : ResourceSource(kSourceExtAudioMap, name, volNum) { + } + + virtual void scanSource(ResourceManager *resMan); +}; + +class WaveResourceSource : public ResourceSource { +public: + WaveResourceSource(const Common::String &name) : ResourceSource(kSourceWave, name) {} + + virtual void loadResource(ResourceManager *resMan, Resource *res); +}; + +/** + * Reads SCI1.1+ resources from a Mac resource fork. + */ +class MacResourceForkResourceSource : public ResourceSource { +protected: + Common::MacResManager *_macResMan; + +public: + MacResourceForkResourceSource(const Common::String &name, int volNum); + ~MacResourceForkResourceSource(); + + virtual void scanSource(ResourceManager *resMan); + + virtual void loadResource(ResourceManager *resMan, Resource *res); +}; + +} // End of namespace Sci + +#endif // SCI_RESOURCE_INTERN_H diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 929bdf3307..1ebc6a2ba3 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -36,22 +36,32 @@ #include "sci/event.h" #include "sci/engine/features.h" +#include "sci/engine/message.h" #include "sci/engine/state.h" #include "sci/engine/kernel.h" #include "sci/engine/script.h" // for script_adjust_opcode_formats +#include "sci/engine/selector.h" // for SELECTOR #include "sci/sound/audio.h" #include "sci/sound/soundcmd.h" -#include "sci/graphics/gui.h" +#include "sci/graphics/animate.h" +#include "sci/graphics/cache.h" +#include "sci/graphics/compare.h" +#include "sci/graphics/controls.h" +#include "sci/graphics/coordadjuster.h" +#include "sci/graphics/cursor.h" #include "sci/graphics/maciconbar.h" +#include "sci/graphics/menu.h" +#include "sci/graphics/paint16.h" +#include "sci/graphics/paint32.h" #include "sci/graphics/ports.h" #include "sci/graphics/palette.h" -#include "sci/graphics/cursor.h" #include "sci/graphics/screen.h" -#include "sci/graphics/cache.h" +#include "sci/graphics/text16.h" +#include "sci/graphics/transitions.h" #ifdef ENABLE_SCI32 -#include "sci/graphics/gui32.h" +#include "sci/graphics/frameout.h" #endif namespace Sci { @@ -61,13 +71,22 @@ SciEngine *g_sci = 0; class GfxDriver; -SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc) - : Engine(syst), _gameDescription(desc), _system(syst) { - _console = NULL; +SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc, SciGameId gameId) + : Engine(syst), _gameDescription(desc), _gameId(gameId) { assert(g_sci == 0); g_sci = this; + + _gfxMacIconBar = 0; + + _audio = 0; _features = 0; + _resMan = 0; + _gamestate = 0; + _kernel = 0; + _vocabulary = 0; + _eventMan = 0; + _console = 0; // Set up the engine specific debug levels DebugMan.addDebugChannel(kDebugLevelError, "Error", "Script error debugging"); @@ -78,10 +97,8 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc) DebugMan.addDebugChannel(kDebugLevelFuncCheck, "Func", "Function parameter debugging"); DebugMan.addDebugChannel(kDebugLevelBresen, "Bresenham", "Bresenham algorithms debugging"); DebugMan.addDebugChannel(kDebugLevelSound, "Sound", "Sound debugging"); - DebugMan.addDebugChannel(kDebugLevelGfxDriver, "Gfxdriver", "Gfx driver debugging"); DebugMan.addDebugChannel(kDebugLevelBaseSetter, "Base", "Base Setter debugging"); DebugMan.addDebugChannel(kDebugLevelParser, "Parser", "Parser debugging"); - DebugMan.addDebugChannel(kDebugLevelMenu, "Menu", "Menu handling debugging"); DebugMan.addDebugChannel(kDebugLevelSaid, "Said", "Said specs debugging"); DebugMan.addDebugChannel(kDebugLevelFile, "File", "File I/O debugging"); DebugMan.addDebugChannel(kDebugLevelTime, "Time", "Time debugging"); @@ -91,26 +108,24 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc) DebugMan.addDebugChannel(kDebugLevelVM, "VM", "VM debugging"); DebugMan.addDebugChannel(kDebugLevelScripts, "Scripts", "Notifies when scripts are unloaded"); DebugMan.addDebugChannel(kDebugLevelGC, "GC", "Garbage Collector debugging"); - DebugMan.addDebugChannel(kDebugLevelSci0Pic, "Sci0Pic", "SCI0 pic drawing debugging"); DebugMan.addDebugChannel(kDebugLevelResMan, "ResMan", "Resource manager debugging"); DebugMan.addDebugChannel(kDebugLevelOnStartup, "OnStartup", "Enter debugger at start of game"); - _gamestate = 0; - _gfxMacIconBar = 0; - const Common::FSNode gameDataDir(ConfMan.get("path")); SearchMan.addSubDirectoryMatching(gameDataDir, "actors"); // KQ6 hi-res portraits SearchMan.addSubDirectoryMatching(gameDataDir, "aud"); // resource.aud and audio files - SearchMan.addSubDirectoryMatching(gameDataDir, "avi"); // AVI movie files for Windows versions - SearchMan.addSubDirectoryMatching(gameDataDir, "seq"); // SEQ movie files for DOS versions SearchMan.addSubDirectoryMatching(gameDataDir, "wav"); // speech files in WAV format SearchMan.addSubDirectoryMatching(gameDataDir, "sfx"); // music/sound files in WAV format - SearchMan.addSubDirectoryMatching(gameDataDir, "robot"); // robot files + SearchMan.addSubDirectoryMatching(gameDataDir, "avi"); // AVI movie files for Windows versions + SearchMan.addSubDirectoryMatching(gameDataDir, "seq"); // SEQ movie files for DOS versions + SearchMan.addSubDirectoryMatching(gameDataDir, "robot"); // robot movie files + SearchMan.addSubDirectoryMatching(gameDataDir, "movies"); // vmd movie files + SearchMan.addSubDirectoryMatching(gameDataDir, "vmd"); // vmd movie files // Add the patches directory, except for KQ6CD; The patches folder in some versions of KQ6CD // is for the demo of Phantasmagoria, included in the disk - if (strcmp(getGameID(), "kq6")) + if (_gameId != GID_KQ6) SearchMan.addSubDirectoryMatching(gameDataDir, "patches"); // resource patches } @@ -118,14 +133,35 @@ SciEngine::~SciEngine() { // Remove all of our debug levels here DebugMan.clearAllDebugChannels(); +#ifdef ENABLE_SCI32 + delete _gfxFrameout; +#endif + delete _gfxMenu; + delete _gfxControls; + delete _gfxText16; + delete _gfxAnimate; + delete _gfxPaint; + delete _gfxTransitions; + delete _gfxCompare; + delete _gfxCoordAdjuster; + delete _gfxPorts; + delete _gfxCache; + delete _gfxPalette; + delete _gfxCursor; + delete _gfxScreen; + delete _audio; + delete _soundCmd; delete _kernel; delete _vocabulary; delete _console; - delete _resMan; delete _features; delete _gfxMacIconBar; + delete _eventMan; + delete _gamestate->_segMan; + delete _gamestate; + delete _resMan; // should be deleted last g_sci = 0; } @@ -135,166 +171,289 @@ Common::Error SciEngine::run() { ConfMan.registerDefault("enable_fb01", "false"); _resMan = new ResourceManager(); + assert(_resMan); + _resMan->addAppropriateSources(); + _resMan->init(); + // TODO: Add error handling. Check return values of addAppropriateSources + // and init. We first have to *add* sensible return values, though ;). +/* if (!_resMan) { warning("No resources found, aborting"); return Common::kNoGameDataFoundError; } +*/ - SegManager *segMan = new SegManager(_resMan); - - // Scale the screen, if needed - int upscaledHires = GFX_SCREEN_UPSCALED_DISABLED; - - // King's Quest 6 and Gabriel Knight 1 have hires content, gk1/cd was able to provide that under DOS as well, but as - // gk1/floppy does support upscaled hires scriptswise, but doesn't actually have the hires content we need to limit - // it to platform windows. - if (getPlatform() == Common::kPlatformWindows) { - if (!strcmp(getGameID(), "kq6")) - upscaledHires = GFX_SCREEN_UPSCALED_640x440; -#ifdef ENABLE_SCI32 - if (!strcmp(getGameID(), "gk1")) - upscaledHires = GFX_SCREEN_UPSCALED_640x480; -#endif - } - - // Japanese versions of games use hi-res font on upscaled version of the game - if ((getLanguage() == Common::JA_JPN) && (getSciVersion() <= SCI_VERSION_1_1)) - upscaledHires = GFX_SCREEN_UPSCALED_640x400; - - // Initialize graphics-related parts - GfxScreen *screen = 0; + // Reset, so that error()s before SoundCommandParser is initialized wont cause a crash + _soundCmd = NULL; - // invokes initGraphics() - if (_resMan->detectHires()) - screen = new GfxScreen(_resMan, 640, 480); - else - screen = new GfxScreen(_resMan, 320, 200, upscaledHires); + // Add the after market GM patches for the specified game, if they exist + _resMan->addNewGMPatch(_gameId); + _gameObj = _resMan->findGameObject(); - if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1) - _gfxMacIconBar = new GfxMacIconBar(); + SegManager *segMan = new SegManager(_resMan); - GfxPalette *palette = new GfxPalette(_resMan, screen); - GfxCache *cache = new GfxCache(_resMan, screen, palette); - GfxCursor *cursor = new GfxCursor(_resMan, palette, screen); + // Initialize the game screen + _gfxScreen = new GfxScreen(_resMan); + _gfxScreen->debugUnditherSetState(ConfMan.getBool("undither")); // Create debugger console. It requires GFX to be initialized _console = new Console(this); - _kernel = new Kernel(_resMan, segMan); + _features = new GameFeatures(segMan, _kernel); // Only SCI0 and SCI01 games used a parser _vocabulary = (getSciVersion() <= SCI_VERSION_1_EGA) ? new Vocabulary(_resMan) : NULL; _audio = new AudioPlayer(_resMan); + _gamestate = new EngineState(segMan); + _eventMan = new EventManager(_resMan->detectFontExtended()); - _features = new GameFeatures(segMan, _kernel); + // The game needs to be initialized before the graphics system is initialized, as + // the graphics code checks parts of the seg manager upon initialization (e.g. for + // the presence of the fastCast object) + if (!initGame()) { /* Initialize */ + warning("Game initialization failed: Aborting..."); + // TODO: Add an "init failed" error? + return Common::kUnknownError; + } - _gamestate = new EngineState(segMan); + script_adjust_opcode_formats(); - _gamestate->_event = new SciEvent(_resMan); + // Must be called after game_init(), as they use _features + _kernel->loadKernelNames(_features); + _soundCmd = new SoundCommandParser(_resMan, segMan, _kernel, _audio, _features->detectDoSoundType()); - if (script_init_engine(_gamestate)) - return Common::kUnknownError; + syncSoundSettings(); -#ifdef ENABLE_SCI32 - if (getSciVersion() >= SCI_VERSION_2) { - _gfxAnimate = 0; - _gfxControls = 0; - _gfxMenu = 0; - _gfxPaint16 = 0; - _gfxPorts = 0; - _gui = 0; - _gui32 = new SciGui32(_gamestate->_segMan, _gamestate->_event, screen, palette, cache, cursor); - } else { -#endif - _gfxPorts = new GfxPorts(segMan, screen); - _gui = new SciGui(_gamestate, screen, palette, cache, cursor, _gfxPorts, _audio); -#ifdef ENABLE_SCI32 - _gui32 = 0; - _gfxFrameout = 0; + // Initialize all graphics related subsystems + initGraphics(); + + debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion())); + + // Check whether loading a savestate was requested + int saveSlot = ConfMan.getInt("save_slot"); + if (saveSlot >= 0) { + reg_t restoreArgv[2] = { NULL_REG, make_reg(0, saveSlot) }; // special call (argv[0] is NULL) + kRestoreGame(_gamestate, 2, restoreArgv); + + // Initialize the game menu, if there is one. + // This is not done when loading, so we must do it manually. + reg_t menuBarObj = _gamestate->_segMan->findObjectByName("MenuBar"); + if (menuBarObj.isNull()) + menuBarObj = _gamestate->_segMan->findObjectByName("TheMenuBar"); // LSL2 + if (menuBarObj.isNull()) + menuBarObj = _gamestate->_segMan->findObjectByName("menuBar"); // LSL6 + if (!menuBarObj.isNull()) { + // Reset abortScriptProcessing before initializing the game menu, so that the + // VM call performed by invokeSelector will actually run. + _gamestate->abortScriptProcessing = kAbortNone; + Object *menuBar = _gamestate->_segMan->getObject(menuBarObj); + // Invoke the first method (init) of the menuBar object + invokeSelector(_gamestate, menuBarObj, menuBar->getFuncSelector(0), 0, _gamestate->stack_base); + _gamestate->abortScriptProcessing = kAbortLoadGame; + } } -#endif - _gfxPalette = palette; - _gfxScreen = screen; - _gfxCache = cache; - _gfxCursor = cursor; + runGame(); - if (game_init(_gamestate)) { /* Initialize */ - warning("Game initialization failed: Aborting..."); - // TODO: Add an "init failed" error? - return Common::kUnknownError; + ConfMan.flushToDisk(); + + return Common::kNoError; +} + +bool SciEngine::initGame() { + // Script 0 needs to be allocated here before anything else! + int script0Segment = _gamestate->_segMan->getScriptSegment(0, SCRIPT_GET_LOCK); + DataStack *stack = _gamestate->_segMan->allocateStack(VM_STACK_SIZE, NULL); + + _gamestate->_msgState = new MessageState(_gamestate->_segMan); + _gamestate->gcCountDown = GC_INTERVAL - 1; + + // Script 0 should always be at segment 1 + if (script0Segment != 1) { + debug(2, "Failed to instantiate script.000"); + return false; } - // Add the after market GM patches for the specified game, if they exist - _resMan->addNewGMPatch(getGameID()); + _gamestate->initGlobals(); - script_adjust_opcode_formats(_gamestate); - _kernel->loadKernelNames(getGameID()); + if (_gamestate->abortScriptProcessing == kAbortRestartGame && _gfxMenu) + _gfxMenu->reset(); - SciVersion soundVersion = _features->detectDoSoundType(); + _gamestate->_segMan->initSysStrings(); - _gamestate->_soundCmd = new SoundCommandParser(_resMan, segMan, _kernel, _audio, soundVersion); + _gamestate->r_acc = _gamestate->r_prev = NULL_REG; - screen->debugUnditherSetState(ConfMan.getBool("undither")); + _gamestate->_executionStack.clear(); // Start without any execution stack + _gamestate->executionStackBase = -1; // No vm is running yet + _gamestate->_executionStackPosChanged = false; -#ifdef USE_OLD_MUSIC_FUNCTIONS - if (game_init_sound(_gamestate, 0, soundVersion)) { - warning("Game initialization failed: Error in sound subsystem. Aborting..."); - return Common::kUnknownError; + _gamestate->abortScriptProcessing = kAbortNone; + _gamestate->gameWasRestarted = false; + + _gamestate->stack_base = stack->_entries; + _gamestate->stack_top = stack->_entries + stack->_capacity; + + if (!_gamestate->_segMan->instantiateScript(0)) { + error("initGame(): Could not instantiate script 0"); + return false; } -#endif - syncSoundSettings(); + // Reset parser + if (_vocabulary) { + _vocabulary->parserIsValid = false; // Invalidate parser + _vocabulary->parser_event = NULL_REG; // Invalidate parser event + _vocabulary->parser_base = make_reg(_gamestate->_segMan->getSysStringsSegment(), SYS_STRING_PARSER_BASE); + } + _gamestate->gameStartTime = _gamestate->lastWaitTime = _gamestate->_screenUpdateTime = g_system->getMillis(); + + srand(g_system->getMillis()); // Initialize random number generator + + // Load game language into printLang property of game object + setSciLanguage(); + + return true; +} + +void SciEngine::initGraphics() { + + // Reset all graphics objects + _gfxAnimate = 0; + _gfxCache = 0; + _gfxCompare = 0; + _gfxControls = 0; + _gfxCoordAdjuster = 0; + _gfxCursor = 0; + _gfxMacIconBar = 0; + _gfxMenu = 0; + _gfxPaint = 0; + _gfxPaint16 = 0; + _gfxPalette = 0; + _gfxPorts = 0; + _gfxText16 = 0; + _gfxTransitions = 0; #ifdef ENABLE_SCI32 - if (_gui32) - _gui32->init(); - else + _gfxFrameout = 0; + _gfxPaint32 = 0; #endif - _gui->init(_features->usesOldGfxFunctions()); - debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion())); + if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1) + _gfxMacIconBar = new GfxMacIconBar(); - // Check whether loading a savestate was requested - if (ConfMan.hasKey("save_slot")) { - _gamestate->loadFromLauncher = ConfMan.getInt("save_slot"); + bool paletteMerging = true; + if (getSciVersion() >= SCI_VERSION_1_1) { + // there are some games that use inbetween SCI1.1 interpreter, so we have to detect if it's merging or copying + if (getSciVersion() == SCI_VERSION_1_1) + paletteMerging = _resMan->detectForPaletteMergingForSci11(); + else + paletteMerging = false; + } + + _gfxPalette = new GfxPalette(_resMan, _gfxScreen, paletteMerging); + _gfxCache = new GfxCache(_resMan, _gfxScreen, _gfxPalette); + _gfxCursor = new GfxCursor(_resMan, _gfxPalette, _gfxScreen); + +#ifdef ENABLE_SCI32 + if (getSciVersion() >= SCI_VERSION_2) { + // SCI32 graphic objects creation + _gfxCoordAdjuster = new GfxCoordAdjuster32(_gamestate->_segMan); + _gfxCursor->init(_gfxCoordAdjuster, _eventMan); + _gfxCompare = new GfxCompare(_gamestate->_segMan, g_sci->getKernel(), _gfxCache, _gfxScreen, _gfxCoordAdjuster); + _gfxPaint32 = new GfxPaint32(g_sci->getResMan(), _gamestate->_segMan, g_sci->getKernel(), _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette); + _gfxPaint = _gfxPaint32; + _gfxFrameout = new GfxFrameout(_gamestate->_segMan, g_sci->getResMan(), _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette, _gfxPaint32); } else { - _gamestate->loadFromLauncher = -1; +#endif + // SCI0-SCI1.1 graphic objects creation + _gfxPorts = new GfxPorts(_gamestate->_segMan, _gfxScreen); + _gfxCoordAdjuster = new GfxCoordAdjuster16(_gfxPorts); + _gfxCursor->init(_gfxCoordAdjuster, g_sci->getEventManager()); + _gfxCompare = new GfxCompare(_gamestate->_segMan, g_sci->getKernel(), _gfxCache, _gfxScreen, _gfxCoordAdjuster); + _gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette, g_sci->getResMan()->isVGA()); + _gfxPaint16 = new GfxPaint16(g_sci->getResMan(), _gamestate->_segMan, g_sci->getKernel(), _gfxCache, _gfxPorts, _gfxCoordAdjuster, _gfxScreen, _gfxPalette, _gfxTransitions, _audio); + _gfxPaint = _gfxPaint16; + _gfxAnimate = new GfxAnimate(_gamestate, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxPalette, _gfxCursor, _gfxTransitions); + _gfxText16 = new GfxText16(g_sci->getResMan(), _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen); + _gfxControls = new GfxControls(_gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen); + _gfxMenu = new GfxMenu(g_sci->getEventManager(), _gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen, _gfxCursor); + + _gfxMenu->reset(); +#ifdef ENABLE_SCI32 } +#endif - game_run(&_gamestate); // Run the game + if (_gfxPorts) { + _gfxPorts->init(_features->usesOldGfxFunctions(), _gfxPaint16, _gfxText16); + _gfxPaint16->init(_gfxAnimate, _gfxText16); + } + // Set default (EGA, amiga or resource 999) palette + _gfxPalette->setDefault(); +} - game_exit(_gamestate); +void SciEngine::initStackBaseWithSelector(Selector selector) { + _gamestate->stack_base[0] = make_reg(0, (uint16)selector); + _gamestate->stack_base[1] = NULL_REG; - ConfMan.flushToDisk(); + // Register the first element on the execution stack + if (!send_selector(_gamestate, _gameObj, _gameObj, _gamestate->stack_base, 2, _gamestate->stack_base)) { + _console->printObject(_gameObj); + error("initStackBaseWithSelector: error while registering the first selector in the call stack"); + } - delete _gamestate->_soundCmd; - delete _gui; -#ifdef ENABLE_SCI32 - delete _gui32; -#endif - delete _gfxPorts; - delete _gfxCache; - delete _gfxPalette; - delete cursor; - delete _gfxScreen; - delete _gamestate->_event; - delete segMan; - delete _gamestate; +} - return Common::kNoError; +void SciEngine::runGame() { + initStackBaseWithSelector(SELECTOR(play)); // Call the play selector + + // Attach the debug console on game startup, if requested + if (DebugMan.isDebugChannelEnabled(kDebugLevelOnStartup)) + _console->attach(); + + do { + _gamestate->_executionStackPosChanged = false; + run_vm(_gamestate, (_gamestate->abortScriptProcessing == kAbortLoadGame)); + exitGame(); + + if (_gamestate->abortScriptProcessing == kAbortRestartGame) { + _gamestate->_segMan->resetSegMan(); + initGame(); + initStackBaseWithSelector(SELECTOR(play)); + _gamestate->gameWasRestarted = true; + } else if (_gamestate->abortScriptProcessing == kAbortLoadGame) { + _gamestate->abortScriptProcessing = kAbortNone; + initStackBaseWithSelector(SELECTOR(replay)); + } else { + break; // exit loop + } + } while (true); +} + +void SciEngine::exitGame() { + if (_gamestate->abortScriptProcessing != kAbortLoadGame) { + _gamestate->_executionStack.clear(); + _audio->stopAllAudio(); + g_sci->_soundCmd->clearPlayList(); + } + + // TODO Free parser segment here + + // TODO Free scripts here + + // Close all opened file handles + _gamestate->_fileHandles.clear(); + _gamestate->_fileHandles.resize(5); } // Invoked by error() when a severe error occurs GUI::Debugger *SciEngine::getDebugger() { if (_gamestate) { ExecStack *xs = &(_gamestate->_executionStack.back()); - xs->addr.pc.offset = g_debugState.old_pc_offset; - xs->sp = g_debugState.old_sp; + xs->addr.pc.offset = _debugState.old_pc_offset; + xs->sp = _debugState.old_sp; } - g_debugState.runningStep = 0; // Stop multiple execution - g_debugState.seeking = kDebugSeekNothing; // Stop special seeks + _debugState.runningStep = 0; // Stop multiple execution + _debugState.seeking = kDebugSeekNothing; // Stop special seeks return _console; } @@ -304,7 +463,7 @@ Console *SciEngine::getSciDebugger() { return _console; } -const char* SciEngine::getGameID() const { +const char *SciEngine::getGameIdStr() const { return _gameDescription->gameid; } @@ -316,12 +475,8 @@ Common::Platform SciEngine::getPlatform() const { return _gameDescription->platform; } -uint32 SciEngine::getFlags() const { - return _gameDescription->flags; -} - bool SciEngine::isDemo() const { - return getFlags() & ADGF_DEMO; + return _gameDescription->flags & ADGF_DEMO; } Common::String SciEngine::getSavegameName(int nr) const { @@ -333,14 +488,12 @@ Common::String SciEngine::getSavegamePattern() const { } Common::String SciEngine::getFilePrefix() const { - const char* gameID = getGameID(); - if (!strcmp(gameID, "qfg2")) { + if (_gameId == GID_QFG2) { // Quest for Glory 2 wants to read files from Quest for Glory 1 (EGA/VGA) to import character data if (_gamestate->currentRoomNumber() == 805) return "qfg1"; // TODO: Include import-room for qfg1vga - } - if (!strcmp(gameID, "qfg3")) { + } else if (_gameId == GID_QFG3) { // Quest for Glory 3 wants to read files from Quest for Glory 2 to import character data if (_gamestate->currentRoomNumber() == 54) return "qfg2"; @@ -361,27 +514,22 @@ Common::String SciEngine::unwrapFilename(const Common::String &name) const { } void SciEngine::pauseEngineIntern(bool pause) { -#ifdef USE_OLD_MUSIC_FUNCTIONS - _gamestate->_sound.sfx_suspend(pause); -#endif _mixer->pauseAll(pause); } void SciEngine::syncSoundSettings() { Engine::syncSoundSettings(); -#ifndef USE_OLD_MUSIC_FUNCTIONS bool mute = false; if (ConfMan.hasKey("mute")) mute = ConfMan.getBool("mute"); int soundVolumeMusic = (mute ? 0 : ConfMan.getInt("music_volume")); - if (_gamestate && _gamestate->_soundCmd) { + if (_gamestate && g_sci->_soundCmd) { int vol = (soundVolumeMusic + 1) * SoundCommandParser::kMaxSciVolume / Audio::Mixer::kMaxMixerVolume; - _gamestate->_soundCmd->setMasterVolume(vol); + g_sci->_soundCmd->setMasterVolume(vol); } -#endif } } // End of namespace Sci diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 685f05e685..c15f87e4e2 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -28,6 +28,8 @@ #include "engines/engine.h" #include "common/util.h" +#include "sci/engine/vm_types.h" // for Selector +#include "sci/debug.h" // for DebugState struct ADGameDescription; @@ -41,9 +43,6 @@ struct ADGameDescription; */ namespace Sci { -// Uncomment this to use old music functions -//#define USE_OLD_MUSIC_FUNCTIONS - struct EngineState; class Vocabulary; class ResourceManager; @@ -51,6 +50,8 @@ class Kernel; class GameFeatures; class Console; class AudioPlayer; +class SoundCommandParser; +class EventManager; class GfxAnimate; class GfxCache; @@ -58,14 +59,16 @@ class GfxCompare; class GfxControls; class GfxCoordAdjuster; class GfxCursor; +class GfxMacIconBar; class GfxMenu; class GfxPaint; class GfxPaint16; +class GfxPaint32; class GfxPalette; class GfxPorts; class GfxScreen; -class SciGui; -class GfxMacIconBar; +class GfxText16; +class GfxTransitions; #ifdef ENABLE_SCI32 class SciGui32; @@ -82,22 +85,89 @@ enum kDebugLevels { kDebugLevelFuncCheck = 1 << 5, kDebugLevelBresen = 1 << 6, kDebugLevelSound = 1 << 7, - kDebugLevelGfxDriver = 1 << 8, - kDebugLevelBaseSetter = 1 << 9, - kDebugLevelParser = 1 << 10, - kDebugLevelMenu = 1 << 11, - kDebugLevelSaid = 1 << 12, - kDebugLevelFile = 1 << 13, - kDebugLevelTime = 1 << 14, - kDebugLevelRoom = 1 << 15, - kDebugLevelAvoidPath = 1 << 16, - kDebugLevelDclInflate = 1 << 17, - kDebugLevelVM = 1 << 18, - kDebugLevelScripts = 1 << 19, - kDebugLevelGC = 1 << 20, - kDebugLevelSci0Pic = 1 << 21, - kDebugLevelResMan = 1 << 22, - kDebugLevelOnStartup = 1 << 23 + kDebugLevelBaseSetter = 1 << 8, + kDebugLevelParser = 1 << 9, + kDebugLevelSaid = 1 << 10, + kDebugLevelFile = 1 << 11, + kDebugLevelTime = 1 << 12, + kDebugLevelRoom = 1 << 13, + kDebugLevelAvoidPath = 1 << 14, + kDebugLevelDclInflate = 1 << 15, + kDebugLevelVM = 1 << 16, + kDebugLevelScripts = 1 << 17, + kDebugLevelGC = 1 << 18, + kDebugLevelResMan = 1 << 19, + kDebugLevelOnStartup = 1 << 20 +}; + +enum SciGameId { + GID_ASTROCHICKEN, + GID_CAMELOT, + GID_CASTLEBRAIN, + GID_CHRISTMAS1988, + GID_CHRISTMAS1990, + GID_CHRISTMAS1992, + GID_CNICK_KQ, + GID_CNICK_LAURABOW, + GID_CNICK_LONGBOW, + GID_CNICK_LSL, + GID_CNICK_SQ, + GID_ECOQUEST, + GID_ECOQUEST2, + GID_FAIRYTALES, + GID_FREDDYPHARKAS, + GID_FUNSEEKER, + GID_GK1, + GID_GK2, + GID_HOYLE1, + GID_HOYLE2, + GID_HOYLE3, + GID_HOYLE4, + GID_ICEMAN, + GID_ISLANDBRAIN, + GID_JONES, + GID_KQ1, + GID_KQ4, + GID_KQ5, + GID_KQ6, + GID_KQ7, + GID_LAURABOW, + GID_LAURABOW2, + GID_LIGHTHOUSE, + GID_LONGBOW, + GID_LSL1, + GID_LSL2, + GID_LSL3, + GID_LSL5, + GID_LSL6, + GID_LSL6HIRES, // We have a separate ID for LSL6 SCI32, because it's actually a completely different game + GID_LSL7, + GID_MOTHERGOOSE, + GID_MSASTROCHICKEN, + GID_PEPPER, + GID_PHANTASMAGORIA, + GID_PHANTASMAGORIA2, + GID_PQ1, + GID_PQ2, + GID_PQ3, + GID_PQ4, + GID_PQSWAT, + GID_QFG1, + GID_QFG2, + GID_QFG3, + GID_QFG4, + GID_RAMA, + GID_SHIVERS, + GID_SHIVERS2, + GID_SLATER, + GID_SQ1, + GID_SQ3, + GID_SQ4, + GID_SQ5, + GID_SQ6, + GID_TORIN, + + GID_FANMADE // FIXME: Do we really need/want this? }; /** SCI versions */ @@ -116,12 +186,6 @@ enum SciVersion { SCI_VERSION_3 // LSL7, RAMA, Lighthouse }; -enum MoveCountType { - kMoveCountUninitialized, - kIgnoreMoveCount, - kIncrementMoveCount -}; - /** Supported languages */ enum kLanguage { K_LANG_NONE = 0, @@ -138,7 +202,7 @@ enum kLanguage { class SciEngine : public Engine { friend class Console; public: - SciEngine(OSystem *syst, const ADGameDescription *desc); + SciEngine(OSystem *syst, const ADGameDescription *desc, SciGameId gameId); ~SciEngine(); // Engine APIs @@ -153,17 +217,19 @@ public: bool canSaveGameStateCurrently(); void syncSoundSettings(); - const char* getGameID() const; + const SciGameId &getGameId() const { return _gameId; } + const char *getGameIdStr() const; int getResourceVersion() const; Common::Language getLanguage() const; Common::Platform getPlatform() const; - uint32 getFlags() const; bool isDemo() const; inline ResourceManager *getResMan() const { return _resMan; } inline Kernel *getKernel() const { return _kernel; } inline EngineState *getEngineState() const { return _gamestate; } inline Vocabulary *getVocabulary() const { return _vocabulary; } + inline EventManager *getEventManager() const { return _eventMan; } + inline reg_t getGameObject() const { return _gameObj; } Common::String getSavegameName(int nr) const; Common::String getSavegamePattern() const; @@ -176,6 +242,12 @@ public: /** Remove the 'TARGET-' prefix of the given filename, if present. */ Common::String unwrapFilename(const Common::String &name) const; + void sleep(uint32 msecs); + + void scriptDebug(); + bool checkExportBreakpoint(uint16 script, uint16 pubfunct); + bool checkSelectorBreakpoint(reg_t send_obj, int selector); + public: /** @@ -189,9 +261,14 @@ public: Common::String strSplit(const char *str, const char *sep = "\r----------\r"); kLanguage getSciLanguage(); + void setSciLanguage(kLanguage lang); + void setSciLanguage(); Common::String getSciLanguageString(const char *str, kLanguage lang, kLanguage *lang2 = NULL) const; + // Initializes ports and paint16 for non-sci32 games, also sets default palette + void initGraphics(); + public: GfxAnimate *_gfxAnimate; // Animate for 16-bit gfx GfxCache *_gfxCache; @@ -203,27 +280,60 @@ public: GfxPalette *_gfxPalette; GfxPaint *_gfxPaint; GfxPaint16 *_gfxPaint16; // Painting in 16-bit gfx + GfxPaint32 *_gfxPaint32; // Painting in 32-bit gfx GfxPorts *_gfxPorts; // Port managment for 16-bit gfx GfxScreen *_gfxScreen; - SciGui *_gui; /* Currently active Gui */ + GfxText16 *_gfxText16; + GfxTransitions *_gfxTransitions; // transitions between screens for 16-bit gfx GfxMacIconBar *_gfxMacIconBar; // Mac Icon Bar manager #ifdef ENABLE_SCI32 - SciGui32 *_gui32; // GUI for SCI32 games GfxFrameout *_gfxFrameout; // kFrameout and the like for 32-bit gfx #endif AudioPlayer *_audio; + SoundCommandParser *_soundCmd; GameFeatures *_features; + DebugState _debugState; + private: + /** + * Initializes a SCI game + * This function must be run before script_run() is executed. Graphics data + * is initialized iff s->gfx_state != NULL. + * @param[in] s The state to operate on + * @return true on success, false if an error occurred. + */ + bool initGame(); + + /** + * Runs a SCI game + * This is the main function for SCI games. It takes a valid state, loads + * script 0 to it, finds the game object, allocates a stack, and runs the + * init method of the game object. In layman's terms, this runs a SCI game. + * @param[in] s Pointer to the pointer of the state to operate on + */ + void runGame(); + + /** + * Uninitializes an initialized SCI game + * This function should be run after each script_run() call. + * @param[in] s The state to operate on + */ + void exitGame(); + + void initStackBaseWithSelector(Selector selector); + const ADGameDescription *_gameDescription; + const SciGameId _gameId; ResourceManager *_resMan; /**< The resource manager */ EngineState *_gamestate; Kernel *_kernel; Vocabulary *_vocabulary; + EventManager *_eventMan; + reg_t _gameObj; /**< Pointer to the game object */ Console *_console; - OSystem *_system; }; diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index 7ecce3b2a3..d9e9d2e8db 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -24,20 +24,21 @@ */ #include "sci/resource.h" -#include "sci/engine/selector.h" #include "sci/engine/kernel.h" +#include "sci/engine/selector.h" #include "sci/engine/seg_manager.h" #include "sci/sound/audio.h" -#include "common/system.h" #include "common/file.h" +#include "common/system.h" #include "sound/audiostream.h" -#include "sound/decoders/raw.h" -#include "sound/decoders/wave.h" +#include "sound/decoders/aiff.h" #include "sound/decoders/flac.h" #include "sound/decoders/mp3.h" +#include "sound/decoders/raw.h" #include "sound/decoders/vorbis.h" +#include "sound/decoders/wave.h" namespace Sci { @@ -45,6 +46,7 @@ AudioPlayer::AudioPlayer(ResourceManager *resMan) : _resMan(resMan), _audioRate( _syncResource(NULL), _syncOffset(0), _audioCdStart(0) { _mixer = g_system->getMixer(); + _wPlayFlag = false; } AudioPlayer::~AudioPlayer() { @@ -63,11 +65,30 @@ int AudioPlayer::startAudio(uint16 module, uint32 number) { Audio::AudioStream *audioStream = getAudioStream(number, module, &sampleLen); if (audioStream) { + _wPlayFlag = false; _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_audioHandle, audioStream); return sampleLen; + } else { + // Don't throw a warning in this case. getAudioStream() already has. Some games + // do miss audio entries (perhaps because of a typo, or because they were simply + // forgotten). + return 0; } +} - return 0; +int AudioPlayer::wPlayAudio(uint16 module, uint32 tuple) { + // Get the audio sample length and set the wPlay flag so we return 0 on + // position. SSCI pre-loads the audio here, but it's much easier for us to + // just get the sample length and return that. wPlayAudio should *not* + // actually start the sample. + + int sampleLen = 0; + Audio::AudioStream *audioStream = getAudioStream(tuple, module, &sampleLen); + if (!audioStream) + warning("wPlayAudio: unable to create stream for audio tuple %d, module %d", tuple, module); + delete audioStream; + _wPlayFlag = true; + return sampleLen; } void AudioPlayer::stopAudio() { @@ -85,6 +106,8 @@ void AudioPlayer::resumeAudio() { int AudioPlayer::getAudioPosition() { if (_mixer->isSoundHandleActive(_audioHandle)) return _mixer->getSoundElapsedTime(_audioHandle) * 6 / 100; // return elapsed time in ticks + else if (_wPlayFlag) + return 0; // Sound has "loaded" so return that it hasn't started else return -1; // Sound finished } @@ -160,17 +183,28 @@ static void deDPCM8(byte *soundBuf, Common::SeekableReadStream &audioStream, uin // Sierra SOL audio file reader // Check here for more info: http://wiki.multimedia.cx/index.php?title=Sierra_Audio -static bool readSOLHeader(Common::SeekableReadStream *audioStream, int headerSize, uint32 &size, uint16 &audioRate, byte &audioFlags) { - if (headerSize != 11 && headerSize != 12) { +static bool readSOLHeader(Common::SeekableReadStream *audioStream, int headerSize, uint32 &size, uint16 &audioRate, byte &audioFlags, uint32 resSize) { + if (headerSize != 7 && headerSize != 11 && headerSize != 12) { warning("SOL audio header of size %i not supported", headerSize); return false; } - audioStream->readUint32LE(); // skip "SOL" + 0 (4 bytes) + uint32 tag = audioStream->readUint32BE(); + + if (tag != MKID_BE('SOL\0')) { + warning("No 'SOL' FourCC found"); + return false; + } + audioRate = audioStream->readUint16LE(); audioFlags = audioStream->readByte(); - size = audioStream->readUint32LE(); + // For the QFG3 demo format, just use the resource size + // Otherwise, load it from the header + if (headerSize == 7) + size = resSize; + else + size = audioStream->readUint32LE(); return true; } @@ -238,9 +272,11 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 // Compressed audio made by our tool byte *compressedData = (byte *)malloc(audioRes->size); assert(compressedData); - // We copy over the compressed data in our own buffer. If we don't do this resourcemanager may free the data - // later. All other compression-types already decompress completely into an additional buffer here. - // MP3/OGG/FLAC decompression works on-the-fly instead. + // We copy over the compressed data in our own buffer. We have to do + // this, because ResourceManager may free the original data late. All + // other compression types already decompress completely into an + // additional buffer here. MP3/OGG/FLAC decompression works on-the-fly + // instead. memcpy(compressedData, audioRes->data, audioRes->size); Common::MemoryReadStream *compressedStream = new Common::MemoryReadStream(compressedData, audioRes->size, DisposeAfterUse::YES); @@ -270,7 +306,7 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 // SCI1.1 Common::MemoryReadStream headerStream(audioRes->_header, audioRes->_headerSize, DisposeAfterUse::NO); - if (readSOLHeader(&headerStream, audioRes->_headerSize, size, _audioRate, audioFlags)) { + if (readSOLHeader(&headerStream, audioRes->_headerSize, size, _audioRate, audioFlags, audioRes->size)) { Common::MemoryReadStream dataStream(audioRes->data, audioRes->size, DisposeAfterUse::NO); data = readSOLAudio(&dataStream, size, audioFlags, flags); } @@ -286,6 +322,18 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 waveStream->seek(0, SEEK_SET); audioStream = Audio::makeWAVStream(waveStream, DisposeAfterUse::YES); + } else if (audioRes->size > 4 && READ_BE_UINT32(audioRes->data) == MKID_BE('FORM')) { + // AIFF detected + Common::MemoryReadStream *waveStream = new Common::MemoryReadStream(audioRes->data, audioRes->size, DisposeAfterUse::NO); + + // Calculate samplelen from AIFF header + int waveSize = 0, waveRate = 0; + byte waveFlags = 0; + Audio::loadAIFFFromStream(*waveStream, waveSize, waveRate, waveFlags); + *sampleLen = (waveFlags & Audio::FLAG_16BITS ? waveSize >> 1 : waveSize) * 60 / waveRate; + + waveStream->seek(0, SEEK_SET); + audioStream = Audio::makeAIFFStream(waveStream, DisposeAfterUse::YES); } else if (audioRes->size > 14 && READ_BE_UINT16(audioRes->data) == 1 && READ_BE_UINT16(audioRes->data + 2) == 1 && READ_BE_UINT16(audioRes->data + 4) == 5 && READ_BE_UINT32(audioRes->data + 10) == 0x00018051) { // Mac snd detected @@ -317,13 +365,12 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 } if (audioSeekStream) { - *sampleLen = (audioSeekStream->getLength().msecs() * 10000) / 166666; // we translate msecs to ticks - // Original code - //*sampleLen = (flags & Audio::FLAG_16BITS ? size >> 1 : size) * 60 / _audioRate; + *sampleLen = (audioSeekStream->getLength().msecs() * 60) / 1000; // we translate msecs to ticks audioStream = audioSeekStream; } - // We have to make sure that we don't depend on resource manager pointers after this point, because the actual - // audio resource may get unloaded by resource manager at any time + // We have to make sure that we don't depend on resource manager pointers + // after this point, because the actual audio resource may get unloaded by + // resource manager at any time. if (audioStream) return audioStream; diff --git a/engines/sci/sound/audio.h b/engines/sci/sound/audio.h index 9fc3cbac51..7c1221fc4c 100644 --- a/engines/sci/sound/audio.h +++ b/engines/sci/sound/audio.h @@ -33,8 +33,7 @@ namespace Sci { enum AudioCommands { - // TODO: find the difference between kSci1AudioWPlay and kSci1AudioPlay - kSciAudioWPlay = 1, /* Plays an audio stream */ + kSciAudioWPlay = 1, /* Loads an audio stream */ kSciAudioPlay = 2, /* Plays an audio stream */ kSciAudioStop = 3, /* Stops an audio stream */ kSciAudioPause = 4, /* Pauses an audio stream */ @@ -69,6 +68,7 @@ public: Audio::RewindableAudioStream *getAudioStream(uint32 number, uint32 volume, int *sampleLen); int getAudioPosition(); int startAudio(uint16 module, uint32 tuple); + int wPlayAudio(uint16 module, uint32 tuple); void stopAudio(); void pauseAudio(); void resumeAudio(); @@ -92,6 +92,7 @@ private: Resource *_syncResource; /**< Used by kDoSync for speech syncing in CD talkie games */ uint _syncOffset; uint32 _audioCdStart; + bool _wPlayFlag; }; } // End of namespace Sci diff --git a/engines/sci/sound/drivers/adlib.cpp b/engines/sci/sound/drivers/adlib.cpp index a743e4b5d9..55c3640c9d 100644 --- a/engines/sci/sound/drivers/adlib.cpp +++ b/engines/sci/sound/drivers/adlib.cpp @@ -704,6 +704,7 @@ void MidiDriver_AdLib::setVelocityReg(int regOffset, int velocity, int kbScaleLe void MidiDriver_AdLib::setPatch(int voice, int patch) { if ((patch < 0) || ((uint)patch >= _patches.size())) { warning("ADLIB: Invalid patch %i requested", patch); + // Substitute instrument 0 patch = 0; } @@ -749,17 +750,24 @@ void MidiDriver_AdLib::playSwitch(bool play) { bool MidiDriver_AdLib::loadResource(const byte *data, uint size) { if ((size != 1344) && (size != 2690) && (size != 5382)) { - warning("ADLIB: Unsupported patch format (%i bytes)", size); + error("ADLIB: Unsupported patch format (%i bytes)", size); return false; } for (int i = 0; i < 48; i++) loadInstrument(data + (28 * i)); - if (size == 2690) { + if (size == 1344) { + byte dummy[28] = {0}; + + // Only 48 instruments, add dummies + for (int i = 0; i < 48; i++) + loadInstrument(dummy); + } else if (size == 2690) { for (int i = 48; i < 96; i++) loadInstrument(data + 2 + (28 * i)); - } else if (size == 5382) { + } else { + // SCI1.1 and later for (int i = 48; i < 190; i++) loadInstrument(data + (28 * i)); _rhythmKeyMap = new byte[kRhythmKeys]; diff --git a/engines/sci/sound/drivers/fb01.cpp b/engines/sci/sound/drivers/fb01.cpp index 7e9fbd51a1..ab9b2e3df5 100644 --- a/engines/sci/sound/drivers/fb01.cpp +++ b/engines/sci/sound/drivers/fb01.cpp @@ -128,8 +128,8 @@ private: }; MidiPlayer_Fb01::MidiPlayer_Fb01(SciVersion version) : MidiPlayer(version), _playSwitch(true), _masterVolume(15), _timerParam(NULL), _timerProc(NULL) { - MidiDriverType midiType = MidiDriver::detectMusicDriver(MDT_MIDI); - _driver = createMidi(midiType); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI); + _driver = createMidi(dev); _sysExBuf[0] = 0x43; _sysExBuf[1] = 0x75; diff --git a/engines/sci/sound/drivers/midi.cpp b/engines/sci/sound/drivers/midi.cpp index 2432a8fab0..1ef0781906 100644 --- a/engines/sci/sound/drivers/midi.cpp +++ b/engines/sci/sound/drivers/midi.cpp @@ -55,6 +55,7 @@ public: bool hasRhythmChannel() const { return true; } byte getPlayId(); int getPolyphony() const { return kVoices; } + int getFirstChannel(); void setVolume(byte volume); int getVolume(); void setReverb(byte reverb); @@ -119,10 +120,10 @@ private: }; MidiPlayer_Midi::MidiPlayer_Midi(SciVersion version) : MidiPlayer(version), _playSwitch(true), _masterVolume(15), _isMt32(false), _hasReverb(false), _isOldPatchFormat(true) { - MidiDriverType midiType = MidiDriver::detectMusicDriver(MDT_MIDI); - _driver = createMidi(midiType); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI); + _driver = createMidi(dev); - if (midiType == MD_MT32 || ConfMan.getBool("native_mt32")) + if (MidiDriver::getMusicType(dev) == MT_MT32 || ConfMan.getBool("native_mt32")) _isMt32 = true; _sysExBuf[0] = 0x41; @@ -271,6 +272,17 @@ void MidiPlayer_Midi::setPatch(int channel, int patch) { _driver->setPitchBendRange(channel, bendRange); _driver->send(0xc0 | channel, _patchMap[patch], 0); + + // Send a pointless command to work around a firmware bug in common + // USB-MIDI cables. If the first MIDI command in a USB packet is a + // Cx or Dx command, the second command in the packet is dropped + // somewhere. + // FIXME: consider putting a workaround in the MIDI backend drivers + // instead. + // Known to be affected: alsa, coremidi + // Known *not* to be affected: windows (only seems to send one MIDI + // command per USB packet even if the device allows larger packets). + _driver->send(0xb0 | channel, 0x0a, _channels[channel].pan); } void MidiPlayer_Midi::send(uint32 b) { @@ -306,6 +318,13 @@ void MidiPlayer_Midi::send(uint32 b) { } } +// We return 1 for mt32, because if we remap channels to 0 for mt32, those won't get played at all +int MidiPlayer_Midi::getFirstChannel() { + if (_isMt32) + return 1; + return 0; +} + void MidiPlayer_Midi::setVolume(byte volume) { _masterVolume = volume; diff --git a/engines/sci/sound/drivers/mididriver.h b/engines/sci/sound/drivers/mididriver.h index 12d3e57f5d..58803db260 100644 --- a/engines/sci/sound/drivers/mididriver.h +++ b/engines/sci/sound/drivers/mididriver.h @@ -86,6 +86,7 @@ public: virtual byte getPlayId() = 0; virtual int getPolyphony() const = 0; + virtual int getFirstChannel() { return 0; }; virtual void setVolume(byte volume) { if(_driver) diff --git a/engines/sci/sound/iterator/core.cpp b/engines/sci/sound/iterator/core.cpp deleted file mode 100644 index 7cd730b3e2..0000000000 --- a/engines/sci/sound/iterator/core.cpp +++ /dev/null @@ -1,1013 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* Sound subsystem core: Event handler, sound player dispatching */ - -#include "sci/sci.h" -#ifdef USE_OLD_MUSIC_FUNCTIONS - -#include "sci/sound/iterator/core.h" -#include "sci/sound/iterator/iterator.h" -#include "sci/sound/drivers/mididriver.h" - -#include "common/system.h" -#include "common/timer.h" - -#include "sound/mixer.h" - -namespace Sci { - -/* Plays a song iterator that found a PCM through a PCM device, if possible -** Parameters: (SongIterator *) it: The iterator to play -** (SongHandle) handle: Debug handle -** Returns : (int) 0 if the effect will not be played, nonzero if it will -** This assumes that the last call to 'it->next()' returned SI_PCM. -*/ -static int sfx_play_iterator_pcm(SongIterator *it, SongHandle handle); - - -#pragma mark - - - -class SfxPlayer { -public: - /** Number of voices that can play simultaneously */ - int _polyphony; - -protected: - SciVersion _soundVersion; - MidiPlayer *_mididrv; - - SongIterator *_iterator; - Audio::Timestamp _wakeupTime; - Audio::Timestamp _currentTime; - uint32 _pauseTimeDiff; - - bool _paused; - bool _iteratorIsDone; - uint32 _tempo; - - Common::Mutex _mutex; - int _volume; - - void play_song(SongIterator *it); - static void player_timer_callback(void *refCon); - -public: - SfxPlayer(SciVersion soundVersion); - ~SfxPlayer(); - - /** - * Initializes the player. - * @param resMan a resource manager for driver initialization - * @param expected_latency expected delay in between calls to 'maintenance' (in microseconds) - * @return Common::kNoError on success, Common::kUnknownError on failure - */ - Common::Error init(ResourceManager *resMan, int expected_latency); - - /** - * Adds an iterator to the song player - * @param it The iterator to play - * @param start_time The time to assume as the time the first MIDI command executes at - * @return Common::kNoError on success, Common::kUnknownError on failure - * - * The iterator should not be cloned (to avoid memory leaks) and - * may be modified according to the needs of the player. - * Implementors may use the 'sfx_iterator_combine()' function - * to add iterators onto their already existing iterators. - */ - Common::Error add_iterator(SongIterator *it, uint32 start_time); - - /** - * Stops the currently playing song and deletes the associated iterator. - * @return Common::kNoError on success, Common::kUnknownError on failure - */ - Common::Error stop(); - - /** - * Transmits a song iterator message to the active song. - * @param msg the message to transmit - * @return Common::kNoError on success, Common::kUnknownError on failure - */ - Common::Error iterator_message(const SongIterator::Message &msg); - - /** - * Pauses song playing. - * @return Common::kNoError on success, Common::kUnknownError on failure - */ - Common::Error pause(); - - /** - * Resumes song playing after a pause. - * @return Common::kNoError on success, Common::kUnknownError on failure - */ - Common::Error resume(); - - /** - * Pass a raw MIDI event to the synth. - * @param argc length of buffer holding the midi event - * @param argv the buffer itself - */ - void tell_synth(int buf_nr, byte *buf); - - void setVolume(int vol); - - int getVolume(); -}; - -SfxPlayer::SfxPlayer(SciVersion soundVersion) - : _soundVersion(soundVersion), _wakeupTime(0, SFX_TICKS_PER_SEC), _currentTime(0, 1) { - _polyphony = 0; - - _mididrv = 0; - - _iterator = NULL; - _pauseTimeDiff = 0; - - _paused = false; - _iteratorIsDone = false; - _tempo = 0; - - _volume = 15; -} - -SfxPlayer::~SfxPlayer() { - if (_mididrv) { - _mididrv->close(); - delete _mididrv; - } - delete _iterator; - _iterator = NULL; -} - -void SfxPlayer::play_song(SongIterator *it) { - while (_iterator && _wakeupTime.msecsDiff(_currentTime) <= 0) { - int delay; - byte buf[8]; - int result; - - switch ((delay = songit_next(&(_iterator), - buf, &result, - IT_READER_MASK_ALL - | IT_READER_MAY_FREE - | IT_READER_MAY_CLEAN))) { - - case SI_FINISHED: - delete _iterator; - _iterator = NULL; - _iteratorIsDone = true; - return; - - case SI_IGNORE: - case SI_LOOP: - case SI_RELATIVE_CUE: - case SI_ABSOLUTE_CUE: - break; - - case SI_PCM: - sfx_play_iterator_pcm(_iterator, 0); - break; - - case 0: - static_cast<MidiDriver *>(_mididrv)->send(buf[0], buf[1], buf[2]); - - break; - - default: - _wakeupTime = _wakeupTime.addFrames(delay); - } - } -} - -void SfxPlayer::tell_synth(int buf_nr, byte *buf) { - byte op1 = (buf_nr < 2 ? 0 : buf[1]); - byte op2 = (buf_nr < 3 ? 0 : buf[2]); - - static_cast<MidiDriver *>(_mididrv)->send(buf[0], op1, op2); -} - -void SfxPlayer::player_timer_callback(void *refCon) { - SfxPlayer *thePlayer = (SfxPlayer *)refCon; - assert(refCon); - Common::StackLock lock(thePlayer->_mutex); - - if (thePlayer->_iterator && !thePlayer->_iteratorIsDone && !thePlayer->_paused) { - thePlayer->play_song(thePlayer->_iterator); - } - - thePlayer->_currentTime = thePlayer->_currentTime.addFrames(1); -} - -/* API implementation */ - -Common::Error SfxPlayer::init(ResourceManager *resMan, int expected_latency) { - MidiDriverType musicDriver = MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_ADLIB); - - switch (musicDriver) { - case MD_ADLIB: - // FIXME: There's no Amiga sound option, so we hook it up to AdLib - if (g_sci->getPlatform() == Common::kPlatformAmiga) - _mididrv = MidiPlayer_Amiga_create(_soundVersion); - else - _mididrv = MidiPlayer_AdLib_create(_soundVersion); - break; - case MD_PCJR: - _mididrv = MidiPlayer_PCJr_create(_soundVersion); - break; - case MD_PCSPK: - _mididrv = MidiPlayer_PCSpeaker_create(_soundVersion); - break; - default: - break; - } - - assert(_mididrv); - - _polyphony = _mididrv->getPolyphony(); - - _tempo = _mididrv->getBaseTempo(); - uint32 time = g_system->getMillis(); - _currentTime = Audio::Timestamp(time, 1000000 / _tempo); - _wakeupTime = Audio::Timestamp(time, SFX_TICKS_PER_SEC); - - _mididrv->setTimerCallback(this, player_timer_callback); - _mididrv->open(resMan); - _mididrv->setVolume(_volume); - - return Common::kNoError; -} - -Common::Error SfxPlayer::add_iterator(SongIterator *it, uint32 start_time) { - Common::StackLock lock(_mutex); - SIMSG_SEND(it, SIMSG_SET_PLAYMASK(_mididrv->getPlayId())); - SIMSG_SEND(it, SIMSG_SET_RHYTHM(_mididrv->hasRhythmChannel())); - - if (_iterator == NULL) { - // Resync with clock - _currentTime = Audio::Timestamp(g_system->getMillis(), 1000000 / _tempo); - _wakeupTime = Audio::Timestamp(start_time, SFX_TICKS_PER_SEC); - } - - _iterator = sfx_iterator_combine(_iterator, it); - _iteratorIsDone = false; - - return Common::kNoError; -} - -Common::Error SfxPlayer::stop() { - debug(3, "Player: Stopping song iterator %p", (void *)_iterator); - Common::StackLock lock(_mutex); - delete _iterator; - _iterator = NULL; - for (int i = 0; i < MIDI_CHANNELS; i++) - static_cast<MidiDriver *>(_mididrv)->send(0xb0 + i, SCI_MIDI_CHANNEL_NOTES_OFF, 0); - - return Common::kNoError; -} - -Common::Error SfxPlayer::iterator_message(const SongIterator::Message &msg) { - Common::StackLock lock(_mutex); - if (!_iterator) { - return Common::kUnknownError; - } - - songit_handle_message(&_iterator, msg); - - return Common::kNoError; -} - -Common::Error SfxPlayer::pause() { - Common::StackLock lock(_mutex); - - _paused = true; - _pauseTimeDiff = _wakeupTime.msecsDiff(_currentTime); - - _mididrv->playSwitch(false); - - return Common::kNoError; -} - -Common::Error SfxPlayer::resume() { - Common::StackLock lock(_mutex); - - _wakeupTime = Audio::Timestamp(_currentTime.msecs() + _pauseTimeDiff, SFX_TICKS_PER_SEC); - _mididrv->playSwitch(true); - _paused = false; - - return Common::kNoError; -} - -void SfxPlayer::setVolume(int vol) { - _mididrv->setVolume(vol); -} - -int SfxPlayer::getVolume() { - return _mididrv->getVolume(); -} - -#pragma mark - - -void SfxState::sfx_reset_player() { - if (_player) - _player->stop(); -} - -void SfxState::sfx_player_tell_synth(int buf_nr, byte *buf) { - if (_player) - _player->tell_synth(buf_nr, buf); -} - -int SfxState::sfx_get_player_polyphony() { - if (_player) - return _player->_polyphony; - else - return 0; -} - -SfxState::SfxState() { - _player = NULL; - _it = NULL; - _flags = 0; - _song = NULL; - _suspended = 0; -} - -SfxState::~SfxState() { -} - - -void SfxState::freezeTime() { - /* Freezes the top song delay time */ - const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); - Song *song = _song; - - while (song) { - song->_delay = song->_wakeupTime.frameDiff(ctime); - if (song->_delay < 0) - song->_delay = 0; - - song = song->_nextPlaying; - } -} - -void SfxState::thawTime() { - /* inverse of freezeTime() */ - const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); - Song *song = _song; - - while (song) { - song->_wakeupTime = ctime.addFrames(song->_delay); - - song = song->_nextPlaying; - } -} - -#if 0 -// Unreferenced - removed -static void _dump_playing_list(SfxState *self, char *msg) { - Song *song = self->_song; - - fprintf(stderr, "[] Song list : [ "); - song = *(self->_songlib.lib); - while (song) { - fprintf(stderr, "%08lx:%d ", song->handle, song->_status); - song = song->_nextPlaying; - } - fprintf(stderr, "]\n"); - - fprintf(stderr, "[] Play list (%s) : [ " , msg); - - while (song) { - fprintf(stderr, "%08lx ", song->handle); - song = song->_nextPlaying; - } - - fprintf(stderr, "]\n"); -} -#endif - -#if 0 -static void _dump_songs(SfxState *self) { - Song *song = self->_song; - - fprintf(stderr, "Cue iterators:\n"); - song = *(self->_songlib.lib); - while (song) { - fprintf(stderr, " **\tHandle %08x (p%d): status %d\n", - song->handle, song->_priority, song->_status); - SIMSG_SEND(song->_it, SIMSG_PRINT(1)); - song = song->_next; - } - - if (self->_player) { - fprintf(stderr, "Audio iterator:\n"); - self->_player->iterator_message(SongIterator::Message(0, SIMSG_PRINT(1))); - } -} -#endif - -bool SfxState::isPlaying(Song *song) { - Song *playing_song = _song; - - /* _dump_playing_list(this, "is-playing");*/ - - while (playing_song) { - if (playing_song == song) - return true; - playing_song = playing_song->_nextPlaying; - } - return false; -} - -void SfxState::setSongStatus(Song *song, int status) { - const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); - - switch (status) { - - case SOUND_STATUS_STOPPED: - // Reset - song->_it->init(); - break; - - case SOUND_STATUS_SUSPENDED: - case SOUND_STATUS_WAITING: - if (song->_status == SOUND_STATUS_PLAYING) { - // Update delay, set wakeup_time - song->_delay += song->_wakeupTime.frameDiff(ctime); - song->_wakeupTime = ctime; - } - if (status == SOUND_STATUS_SUSPENDED) - break; - - /* otherwise... */ - - case SOUND_STATUS_PLAYING: - if (song->_status == SOUND_STATUS_STOPPED) { - // Starting anew - song->_wakeupTime = ctime; - } - - if (isPlaying(song)) - status = SOUND_STATUS_PLAYING; - else - status = SOUND_STATUS_WAITING; - break; - - default: - fprintf(stderr, "%s L%d: Attempt to set invalid song" - " state %d!\n", __FILE__, __LINE__, status); - return; - - } - song->_status = status; -} - -/* Update internal state iff only one song may be played */ -void SfxState::updateSingleSong() { - Song *newsong = _songlib.findFirstActive(); - - if (newsong != _song) { - freezeTime(); /* Store song delay time */ - - if (_player) - _player->stop(); - - if (newsong) { - if (!newsong->_it) - return; /* Restore in progress and not ready for this yet */ - - /* Change song */ - if (newsong->_status == SOUND_STATUS_WAITING) - setSongStatus(newsong, SOUND_STATUS_PLAYING); - - /* Change instrument mappings */ - } else { - /* Turn off sound */ - } - if (_song) { - if (_song->_status == SOUND_STATUS_PLAYING) - setSongStatus(newsong, SOUND_STATUS_WAITING); - } - - Common::String debugMessage = "[SFX] Changing active song:"; - if (!_song) { - debugMessage += " New song:"; - } else { - char tmp[50]; - sprintf(tmp, " pausing %08lx, now playing ", _song->_handle); - debugMessage += tmp; - } - - if (newsong) { - char tmp[20]; - sprintf(tmp, "%08lx\n", newsong->_handle); - debugMessage += tmp; - } else { - debugMessage += " none\n"; - } - - debugC(2, kDebugLevelSound, "%s", debugMessage.c_str()); - - _song = newsong; - thawTime(); /* Recover song delay time */ - - if (newsong && _player) { - SongIterator *clonesong = newsong->_it->clone(newsong->_delay); - - _player->add_iterator(clonesong, newsong->_wakeupTime.msecs()); - } - } -} - - -void SfxState::updateMultiSong() { - Song *oldfirst = _song; - Song *oldseeker; - Song *newsong = _songlib.findFirstActive(); - Song *newseeker; - Song not_playing_anymore; /* Dummy object, referenced by - ** songs which are no longer - ** active. */ - - /* _dump_playing_list(this, "before");*/ - freezeTime(); /* Store song delay time */ - - // WORKAROUND: sometimes, newsong can be NULL (e.g. in SQ4). - // Handle this here, so that we avoid a crash - if (!newsong) { - // Iterators should get freed when there's only one song left playing - if(oldfirst && oldfirst->_status == SOUND_STATUS_STOPPED) { - debugC(2, kDebugLevelSound, "[SFX] Stopping song %lx", oldfirst->_handle); - if (_player && oldfirst->_it) - _player->iterator_message(SongIterator::Message(oldfirst->_it->ID, SIMSG_STOP)); - } - return; - } - - for (newseeker = newsong; newseeker; - newseeker = newseeker->_nextPlaying) { - if (!newseeker || !newseeker->_it) - return; /* Restore in progress and not ready for this yet */ - } - - /* First, put all old songs into the 'stopping' list and - ** mark their 'next-playing' as not_playing_anymore. */ - for (oldseeker = oldfirst; oldseeker; - oldseeker = oldseeker->_nextStopping) { - oldseeker->_nextStopping = oldseeker->_nextPlaying; - oldseeker->_nextPlaying = ¬_playing_anymore; - - if (oldseeker == oldseeker->_nextPlaying) { - error("updateMultiSong() failed. Breakpoint in %s, line %d", __FILE__, __LINE__); - } - } - - /* Second, re-generate the new song queue. */ - for (newseeker = newsong; newseeker; newseeker = newseeker->_nextPlaying) { - newseeker->_nextPlaying = _songlib.findNextActive(newseeker); - - if (newseeker == newseeker->_nextPlaying) { - error("updateMultiSong() failed. Breakpoint in %s, line %d", __FILE__, __LINE__); - } - } - /* We now need to update the currently playing song list, because we're - ** going to use some functions that require this list to be in a sane - ** state (particularly isPlaying(), indirectly */ - _song = newsong; - - /* Third, stop all old songs */ - for (oldseeker = oldfirst; oldseeker; - oldseeker = oldseeker->_nextStopping) - if (oldseeker->_nextPlaying == ¬_playing_anymore) { - setSongStatus(oldseeker, SOUND_STATUS_SUSPENDED); - debugC(2, kDebugLevelSound, "[SFX] Stopping song %lx", oldseeker->_handle); - - if (_player && oldseeker->_it) - _player->iterator_message(SongIterator::Message(oldseeker->_it->ID, SIMSG_STOP)); - oldseeker->_nextPlaying = NULL; /* Clear this pointer; we don't need the tag anymore */ - } - - for (newseeker = newsong; newseeker; newseeker = newseeker->_nextPlaying) { - if (newseeker->_status != SOUND_STATUS_PLAYING && _player) { - debugC(2, kDebugLevelSound, "[SFX] Adding song %lx", newseeker->_it->ID); - - SongIterator *clonesong = newseeker->_it->clone(newseeker->_delay); - _player->add_iterator(clonesong, g_system->getMillis()); - } - setSongStatus(newseeker, SOUND_STATUS_PLAYING); - } - - _song = newsong; - thawTime(); - /* _dump_playing_list(this, "after");*/ -} - -/* Update internal state */ -void SfxState::update() { - if (_flags & SFX_STATE_FLAG_MULTIPLAY) - updateMultiSong(); - else - updateSingleSong(); -} - -static int sfx_play_iterator_pcm(SongIterator *it, SongHandle handle) { -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Playing PCM: %08lx\n", handle); -#endif - if (g_system->getMixer()->isReady()) { - Audio::AudioStream *newfeed = it->getAudioStream(); - if (newfeed) { - g_system->getMixer()->playStream(Audio::Mixer::kSFXSoundType, 0, newfeed); - return 1; - } - } - return 0; -} - -#define DELAY (1000000 / SFX_TICKS_PER_SEC) - -void SfxState::sfx_init(ResourceManager *resMan, int flags, SciVersion soundVersion) { - _songlib._lib = 0; - _song = NULL; - _flags = flags; - - _player = NULL; - - if (flags & SFX_STATE_FLAG_NOSOUND) { - warning("[SFX] Sound disabled"); - return; - } - -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Initialising: flags=%x\n", flags); -#endif - - /*-------------------*/ - /* Initialise player */ - /*-------------------*/ - - if (!resMan) { - warning("[SFX] Warning: No resource manager present, cannot initialise player"); - return; - } - - _player = new SfxPlayer(soundVersion); - - if (!_player) { - warning("[SFX] No song player found"); - return; - } - - if (_player->init(resMan, DELAY / 1000)) { - warning("[SFX] Song player reported error, disabled"); - delete _player; - _player = NULL; - } - - _resMan = resMan; -} - -void SfxState::sfx_exit() { -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Uninitialising\n"); -#endif - - delete _player; - _player = 0; - - g_system->getMixer()->stopAll(); - - _songlib.freeSounds(); -} - -void SfxState::sfx_suspend(bool suspend) { -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Suspending? = %d\n", suspend); -#endif - if (suspend && (!_suspended)) { - /* suspend */ - - freezeTime(); - if (_player) - _player->pause(); - /* Suspend song player */ - - } else if (!suspend && (_suspended)) { - /* unsuspend */ - - thawTime(); - if (_player) - _player->resume(); - - /* Unsuspend song player */ - } - - _suspended = suspend; -} - -int SfxState::sfx_poll(SongHandle *handle, int *cue) { - if (!_song) - return 0; /* No milk today */ - - *handle = _song->_handle; - -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Polling any (%08lx)\n", *handle); -#endif - return sfx_poll_specific(*handle, cue); -} - -int SfxState::sfx_poll_specific(SongHandle handle, int *cue) { - const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); - Song *song = _song; - - while (song && song->_handle != handle) - song = song->_nextPlaying; - - if (!song) - return 0; /* Song not playing */ - - debugC(2, kDebugLevelSound, "[SFX:CUE] Polled song %08lx ", handle); - - while (1) { - if (song->_wakeupTime.frameDiff(ctime) > 0) - return 0; /* Patience, young hacker! */ - - byte buf[8]; - int result = songit_next(&(song->_it), buf, cue, IT_READER_MASK_ALL); - - switch (result) { - - case SI_FINISHED: - setSongStatus(song, SOUND_STATUS_STOPPED); - update(); - /* ...fall through... */ - case SI_LOOP: - case SI_RELATIVE_CUE: - case SI_ABSOLUTE_CUE: - if (result == SI_FINISHED) - debugC(2, kDebugLevelSound, " => finished"); - else { - if (result == SI_LOOP) - debugC(2, kDebugLevelSound, " => Loop: %d (0x%x)", *cue, *cue); - else - debugC(2, kDebugLevelSound, " => Cue: %d (0x%x)", *cue, *cue); - - } - return result; - - default: - if (result > 0) - song->_wakeupTime = song->_wakeupTime.addFrames(result); - - /* Delay */ - break; - } - } - -} - - -/*****************/ -/* Song basics */ -/*****************/ - -void SfxState::sfx_add_song(SongIterator *it, int priority, SongHandle handle, int number) { - Song *song = _songlib.findSong(handle); - -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Adding song: %08lx at %d, it=%p\n", handle, priority, it); -#endif - if (!it) { - error("[SFX] Attempt to add empty song with handle %08lx", handle); - return; - } - - it->init(); - - /* If we're already playing this, stop it */ - /* Tell player to shut up */ -// _dump_songs(this); - - if (_player) - _player->iterator_message(SongIterator::Message(handle, SIMSG_STOP)); - - if (song) { - setSongStatus( song, SOUND_STATUS_STOPPED); - - fprintf(stderr, "Overwriting old song (%08lx) ...\n", handle); - if (song->_status == SOUND_STATUS_PLAYING || song->_status == SOUND_STATUS_SUSPENDED) { - delete it; - error("Unexpected (error): Song %ld still playing/suspended (%d)", - handle, song->_status); - return; - } else { - _songlib.removeSong(handle); /* No duplicates */ - } - - } - - song = new Song(handle, it, priority); - song->_resourceNum = number; - song->_hold = 0; - song->_loops = 0; - song->_wakeupTime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); - _songlib.addSong(song); - _song = NULL; /* As above */ - update(); - - return; -} - -void SfxState::sfx_remove_song(SongHandle handle) { -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Removing song: %08lx\n", handle); -#endif - if (_song && _song->_handle == handle) - _song = NULL; - - _songlib.removeSong(handle); - update(); -} - - - -/**********************/ -/* Song modifications */ -/**********************/ - -#define ASSERT_SONG(s) if (!(s)) { warning("Looking up song handle %08lx failed in %s, L%d", handle, __FILE__, __LINE__); return; } - -void SfxState::sfx_song_set_status(SongHandle handle, int status) { - Song *song = _songlib.findSong(handle); - ASSERT_SONG(song); -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Setting song status to %d" - " (0:stop, 1:play, 2:susp, 3:wait): %08lx\n", status, handle); -#endif - - setSongStatus(song, status); - - update(); -} - -void SfxState::sfx_song_set_fade(SongHandle handle, fade_params_t *params) { -#ifdef DEBUG_SONG_API - static const char *stopmsg[] = {"??? Should not happen", "Do not stop afterwards", "Stop afterwards"}; -#endif - Song *song = _songlib.findSong(handle); - - ASSERT_SONG(song); - -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Setting fade params of %08lx to " - "final volume %d in steps of %d per %d ticks. %s.", - handle, fade->final_volume, fade->step_size, fade->ticks_per_step, - stopmsg[fade->action]); -#endif - - SIMSG_SEND_FADE(song->_it, params); - - update(); -} - -void SfxState::sfx_song_renice(SongHandle handle, int priority) { - Song *song = _songlib.findSong(handle); - ASSERT_SONG(song); -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Renicing song %08lx to %d\n", - handle, priority); -#endif - - song->_priority = priority; - - update(); -} - -void SfxState::sfx_song_set_loops(SongHandle handle, int loops) { - Song *song = _songlib.findSong(handle); - SongIterator::Message msg = SongIterator::Message(handle, SIMSG_SET_LOOPS(loops)); - ASSERT_SONG(song); - - song->_loops = loops; -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Setting loops on %08lx to %d\n", - handle, loops); -#endif - songit_handle_message(&(song->_it), msg); - - if (_player/* && _player->send_iterator_message*/) - /* FIXME: The above should be optional! */ - _player->iterator_message(msg); -} - -void SfxState::sfx_song_set_hold(SongHandle handle, int hold) { - Song *song = _songlib.findSong(handle); - SongIterator::Message msg = SongIterator::Message(handle, SIMSG_SET_HOLD(hold)); - ASSERT_SONG(song); - - song->_hold = hold; -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Setting hold on %08lx to %d\n", - handle, hold); -#endif - songit_handle_message(&(song->_it), msg); - - if (_player/* && _player->send_iterator_message*/) - /* FIXME: The above should be optional! */ - _player->iterator_message(msg); -} - -/* Different from the one in iterator.c */ -static const int MIDI_cmdlen[16] = {0, 0, 0, 0, 0, 0, 0, 0, - 3, 3, 0, 3, 2, 0, 3, 0 - }; - -static const SongHandle midi_send_base = 0xffff0000; - -Common::Error SfxState::sfx_send_midi(SongHandle handle, int channel, - int command, int arg1, int arg2) { - byte buffer[5]; - - /* Yes, in that order. SCI channel mutes are actually done via - a counting semaphore. 0 means to decrement the counter, 1 - to increment it. */ - static const char *channel_state[] = {"ON", "OFF"}; - - if (command == 0xb0 && - arg1 == SCI_MIDI_CHANNEL_MUTE) { - warning("TODO: channel mute (channel %d %s)", channel, channel_state[arg2]); - /* We need to have a GET_PLAYMASK interface to use - here. SET_PLAYMASK we've got. - */ - return Common::kNoError; - } - - buffer[0] = channel | command; /* No channel remapping yet */ - - switch (command) { - case 0x80 : - case 0x90 : - case 0xb0 : - buffer[1] = arg1 & 0xff; - buffer[2] = arg2 & 0xff; - break; - case 0xc0 : - buffer[1] = arg1 & 0xff; - break; - case 0xe0 : - buffer[1] = (arg1 & 0x7f) | 0x80; - buffer[2] = (arg1 & 0xff00) >> 7; - break; - default: - warning("Unexpected explicit MIDI command %02x", command); - return Common::kUnknownError; - } - - if (_player) - _player->tell_synth(MIDI_cmdlen[command >> 4], buffer); - return Common::kNoError; -} - -int SfxState::sfx_getVolume() { - return _player->getVolume(); -} - -void SfxState::sfx_setVolume(int volume) { - _player->setVolume(volume); -} - -void SfxState::sfx_all_stop() { -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] All stop\n"); -#endif - - _songlib.freeSounds(); - update(); -} - -} // End of namespace Sci - -#endif // USE_OLD_MUSIC_FUNCTIONS diff --git a/engines/sci/sound/iterator/core.h b/engines/sci/sound/iterator/core.h deleted file mode 100644 index a44fe2ecae..0000000000 --- a/engines/sci/sound/iterator/core.h +++ /dev/null @@ -1,209 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* Sound engine */ -#ifndef SCI_SFX_CORE_H -#define SCI_SFX_CORE_H - -#include "common/error.h" - -#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS - -#ifdef USE_OLD_MUSIC_FUNCTIONS -#include "sci/sound/iterator/songlib.h" -#include "sci/resource.h" - -namespace Sci { - -class SfxPlayer; -class SongIterator; -struct fade_params_t; - -#define SFX_TICKS_PER_SEC 60 /* MIDI ticks per second */ - - -#define SFX_STATE_FLAG_MULTIPLAY (1 << 0) /* More than one song playable -** simultaneously ? */ -#define SFX_STATE_FLAG_NOSOUND (1 << 1) /* Completely disable sound playing */ - -class SfxState { -private: - SfxPlayer *_player; - -public: // FIXME, make private - SongIterator *_it; /**< The song iterator at the heart of things */ - uint _flags; /**< SFX_STATE_FLAG_* */ - SongLibrary _songlib; /**< Song library */ - Song *_song; /**< Active song, or start of active song chain */ - bool _suspended; /**< Whether we are suspended */ - ResourceManager *_resMan; - -public: - SfxState(); - ~SfxState(); - - /***********/ - /* General */ - /***********/ - - /* Initializes the sound engine - ** Parameters: (ResourceManager *) resMan: Resource manager for initialization - ** (int) flags: SFX_STATE_FLAG_* - */ - void sfx_init(ResourceManager *resMan, int flags, SciVersion soundVersion); - - /** Deinitializes the sound subsystem. */ - void sfx_exit(); - - /* Suspends/unsuspends the sound sybsystem - ** Parameters: (int) suspend: Whether to suspend (non-null) or to unsuspend - */ - void sfx_suspend(bool suspend); - - /* Polls the sound server for cues etc. - ** Returns : (int) 0 if the cue queue is empty, SI_LOOP, SI_CUE, or SI_FINISHED otherwise - ** (SongHandle) *handle: The affected handle - ** (int) *cue: The sound cue number (if SI_CUE), or the loop number (if SI_LOOP) - */ - int sfx_poll(SongHandle *handle, int *cue); - - /* Polls the sound server for cues etc. - ** Parameters: (SongHandle) handle: The handle to poll - ** Returns : (int) 0 if the cue queue is empty, SI_LOOP, SI_CUE, or SI_FINISHED otherwise - ** (int) *cue: The sound cue number (if SI_CUE), or the loop number (if SI_LOOP) - */ - int sfx_poll_specific(SongHandle handle, int *cue); - - /* Determines the current global volume settings - ** Returns : (int) The global volume, between 0 (silent) and 127 (max. volume) - */ - int sfx_getVolume(); - - /* Determines the current global volume settings - ** Parameters: (int) volume: The new global volume, between 0 and 127 (see above) - */ - void sfx_setVolume(int volume); - - /* Stops all songs currently playing, purges song library - */ - void sfx_all_stop(); - - - /*****************/ - /* Song basics */ - /*****************/ - - /* Adds a song to the internal sound library - ** Parameters: (SongIterator *) it: The iterator describing the song - ** (int) priority: Initial song priority (higher <-> more important) - ** (SongHandle) handle: The handle to associate with the song - */ - void sfx_add_song(SongIterator *it, int priority, SongHandle handle, int resnum); - - - /* Deletes a song and its associated song iterator from the song queue - ** Parameters: (SongHandle) handle: The song to remove - */ - void sfx_remove_song(SongHandle handle); - - - /**********************/ - /* Song modifications */ - /**********************/ - - - /* Sets the song status, i.e. whether it is playing, suspended, or stopped. - ** Parameters: (SongHandle) handle: Handle of the song to modify - ** (int) status: The song status the song should assume - ** WAITING and PLAYING are set implicitly and essentially describe the same state - ** as far as this function is concerned. - */ - void sfx_song_set_status(SongHandle handle, int status); - - /* Sets the new song priority - ** Parameters: (SongHandle) handle: The handle to modify - ** (int) priority: The priority to set - */ - void sfx_song_renice(SongHandle handle, int priority); - - /* Sets the number of loops for the specified song - ** Parameters: (SongHandle) handle: The song handle to reference - ** (int) loops: Number of loops to set - */ - void sfx_song_set_loops(SongHandle handle, int loops); - - /* Sets the number of loops for the specified song - ** Parameters: (SongHandle) handle: The song handle to reference - ** (int) hold: Number of loops to setn - */ - void sfx_song_set_hold(SongHandle handle, int hold); - - /* Instructs a song to be faded out - ** Parameters: (SongHandle) handle: The song handle to reference - ** (fade_params_t *) fade_setup: The precise fade-out configuration to use - */ - void sfx_song_set_fade(SongHandle handle, fade_params_t *fade_setup); - - - // Previously undocumented: - Common::Error sfx_send_midi(SongHandle handle, int channel, - int command, int arg1, int arg2); - - // misc - - /** - * Determines the polyphony of the player in use. - * @return Number of voices the active player can emit - */ - int sfx_get_player_polyphony(); - - /** - * Tells the player to stop its internal iterator. - */ - void sfx_reset_player(); - - /** - * Pass a raw MIDI event to the synth of the player. - * @param argc Length of buffer holding the midi event - * @param argv The buffer itself - */ - void sfx_player_tell_synth(int buf_nr, byte *buf); - -protected: - void freezeTime(); - void thawTime(); - - bool isPlaying(Song *song); - void setSongStatus(Song *song, int status); - void updateSingleSong(); - void updateMultiSong(); - void update(); -}; - -} // End of namespace Sci - -#endif // USE_OLD_MUSIC_FUNCTIONS - -#endif // SCI_SFX_CORE_H diff --git a/engines/sci/sound/iterator/iterator.cpp b/engines/sci/sound/iterator/iterator.cpp deleted file mode 100644 index 5d9d63e5af..0000000000 --- a/engines/sci/sound/iterator/iterator.cpp +++ /dev/null @@ -1,1686 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* Song iterators */ - -#include "common/util.h" - -#include "sci/sci.h" -#ifdef USE_OLD_MUSIC_FUNCTIONS - -#include "sci/sound/iterator/iterator_internal.h" -#include "sci/engine/state.h" // for sfx_player_tell_synth :/ -#include "sci/sound/iterator/core.h" // for sfx_player_tell_synth - -#include "sound/audiostream.h" -#include "sound/mixer.h" -#include "sound/decoders/raw.h" - -namespace Sci { - - -static const int MIDI_cmdlen[16] = {0, 0, 0, 0, 0, 0, 0, 0, - 2, 2, 2, 2, 1, 1, 2, 0 - }; - -/*#define DEBUG_DECODING*/ -/*#define DEBUG_VERBOSE*/ - -/** Find first set bit in bits and return its index. Returns 0 if bits is 0. */ -static int sci_ffs(int bits) { - if (!bits) - return 0; - - int retval = 1; - - while (!(bits & 1)) { - retval++; - bits >>= 1; - } - - return retval; -} - -static void print_tabs_id(int nr, songit_id_t id) { - while (nr-- > 0) - fprintf(stderr, "\t"); - - fprintf(stderr, "[%08lx] ", id); -} - -BaseSongIterator::BaseSongIterator(byte *data, uint size, songit_id_t id) - : _data(data, size) { - ID = id; -} - -/************************************/ -/*-- SCI0 iterator implementation --*/ -/************************************/ - -#define SCI0_MIDI_OFFSET 33 -#define SCI0_END_OF_SONG 0xfc /* proprietary MIDI command */ - -#define SCI0_PCM_SAMPLE_RATE_OFFSET 0x0e -#define SCI0_PCM_SIZE_OFFSET 0x20 -#define SCI0_PCM_DATA_OFFSET 0x2c - -#define CHECK_FOR_END_ABSOLUTE(offset) \ - if (offset > _data.size()) { \ - warning("Reached end of song without terminator (%x/%x) at %d", offset, _data.size(), __LINE__); \ - return SI_FINISHED; \ - } - -#define CHECK_FOR_END(offset_augment) \ - if ((channel->offset + (offset_augment)) > channel->end) { \ - channel->state = SI_STATE_FINISHED; \ - warning("Reached end of track %d without terminator (%x+%x/%x) at %d", channel->id, channel->offset, offset_augment, channel->end, __LINE__); \ - return SI_FINISHED; \ - } - - -static int _parse_ticks(byte *data, int *offset_p, int size) { - int ticks = 0; - int tempticks; - int offset = 0; - - do { - tempticks = data[offset++]; - ticks += (tempticks == SCI_MIDI_TIME_EXPANSION_PREFIX) ? - SCI_MIDI_TIME_EXPANSION_LENGTH : tempticks; - } while (tempticks == SCI_MIDI_TIME_EXPANSION_PREFIX - && offset < size); - - if (offset_p) - *offset_p = offset; - - return ticks; -} - - -static int _sci0_get_pcm_data(Sci0SongIterator *self, int *rate, int *xoffset, uint *xsize); - - -#define PARSE_FLAG_LOOPS_UNLIMITED (1 << 0) /* Unlimited # of loops? */ -#define PARSE_FLAG_PARAMETRIC_CUE (1 << 1) /* Assume that cues take an additional "cue value" argument */ -/* This implements a difference between SCI0 and SCI1 cues. */ - -void SongIteratorChannel::init(int id_, int offset_, int end_) { - playmask = PLAYMASK_NONE; /* Disable all channels */ - id = id_; - state = SI_STATE_DELTA_TIME; - loop_timepos = 0; - total_timepos = 0; - timepos_increment = 0; - delay = 0; /* Only used for more than one channel */ - last_cmd = 0xfe; - - offset = loop_offset = initial_offset = offset_; - end = end_; -} - -void SongIteratorChannel::resetSynthChannels() { - byte buf[5]; - - // FIXME: Evil hack - SfxState &sound = g_sci->getEngineState()->_sound; - - for (int i = 0; i < MIDI_CHANNELS; i++) { - if (playmask & (1 << i)) { - buf[0] = 0xe0 | i; /* Pitch bend */ - buf[1] = 0x80; /* Wheel center */ - buf[2] = 0x40; - sound.sfx_player_tell_synth(3, buf); - - buf[0] = 0xb0 | i; // Set control - buf[1] = 0x40; // Hold pedal - buf[2] = 0x00; // Off - sound.sfx_player_tell_synth(3, buf); - /* TODO: Reset other controls? */ - } - } -} - -int BaseSongIterator::parseMidiCommand(byte *buf, int *result, SongIteratorChannel *channel, int flags) { - byte cmd; - int paramsleft; - int midi_op; - int midi_channel; - - channel->state = SI_STATE_DELTA_TIME; - - cmd = _data[channel->offset++]; - - if (!(cmd & 0x80)) { - /* 'Running status' mode */ - channel->offset--; - cmd = channel->last_cmd; - } - - if (cmd == 0xfe) { - warning("song iterator subsystem: Corrupted sound resource detected."); - return SI_FINISHED; - } - - midi_op = cmd >> 4; - midi_channel = cmd & 0xf; - paramsleft = MIDI_cmdlen[midi_op]; - -#if 0 - if (1) { - fprintf(stderr, "[IT]: off=%x, cmd=%02x, takes %d args ", - channel->offset - 1, cmd, paramsleft); - fprintf(stderr, "[%02x %02x <%02x> %02x %02x %02x]\n", - _data[channel->offset-3], - _data[channel->offset-2], - _data[channel->offset-1], - _data[channel->offset], - _data[channel->offset+1], - _data[channel->offset+2]); - } -#endif - - buf[0] = cmd; - - - CHECK_FOR_END(paramsleft); - memcpy(buf + 1, _data.begin() + channel->offset, paramsleft); - *result = 1 + paramsleft; - - channel->offset += paramsleft; - - channel->last_cmd = cmd; - - /* Are we supposed to play this channel? */ - if ( - /* First, exclude "global" properties-- such as cues-- from consideration */ - (midi_op < 0xf - && !(cmd == SCI_MIDI_SET_SIGNAL) - && !(SCI_MIDI_CONTROLLER(cmd) - && buf[1] == SCI_MIDI_CUMULATIVE_CUE)) - - /* Next, check if the channel is allowed */ - && (!((1 << midi_channel) & channel->playmask))) - return /* Execute next command */ - nextCommand(buf, result); - - - if (cmd == SCI_MIDI_EOT) { - /* End of track? */ - channel->resetSynthChannels(); - if (_loops > 1) { - /* If allowed, decrement the number of loops */ - if (!(flags & PARSE_FLAG_LOOPS_UNLIMITED)) - *result = --_loops; - -#ifdef DEBUG_DECODING - fprintf(stderr, "%s L%d: (%p):%d Looping ", __FILE__, __LINE__, this, channel->id); - if (flags & PARSE_FLAG_LOOPS_UNLIMITED) - fprintf(stderr, "(indef.)"); - else - fprintf(stderr, "(%d)", _loops); - fprintf(stderr, " %x -> %x\n", - channel->offset, channel->loop_offset); -#endif - channel->offset = channel->loop_offset; - channel->state = SI_STATE_DELTA_TIME; - channel->total_timepos = channel->loop_timepos; - channel->last_cmd = 0xfe; - debugC(2, kDebugLevelSound, "Looping song iterator %08lx.", ID); - return SI_LOOP; - } else { - channel->state = SI_STATE_FINISHED; - return SI_FINISHED; - } - - } else if (cmd == SCI_MIDI_SET_SIGNAL) { - if (buf[1] == SCI_MIDI_SET_SIGNAL_LOOP) { - channel->loop_offset = channel->offset; - channel->loop_timepos = channel->total_timepos; - - return /* Execute next command */ - nextCommand(buf, result); - } else { - /* Used to be conditional <= 127 */ - *result = buf[1]; /* Absolute cue */ - return SI_ABSOLUTE_CUE; - } - } else if (SCI_MIDI_CONTROLLER(cmd)) { - switch (buf[1]) { - - case SCI_MIDI_CUMULATIVE_CUE: - if (flags & PARSE_FLAG_PARAMETRIC_CUE) - _ccc += buf[2]; - else { /* No parameter to CC */ - _ccc++; - /* channel->offset--; */ - } - *result = _ccc; - return SI_RELATIVE_CUE; - - case SCI_MIDI_RESET_ON_SUSPEND: - _resetflag = buf[2]; - break; - - case SCI_MIDI_SET_POLYPHONY: - _polyphony[midi_channel] = buf[2]; - -#if 0 - { - Sci1SongIterator *self1 = (Sci1SongIterator *)this; - int i; - int voices = 0; - for (i = 0; i < self1->_numChannels; i++) { - voices += _polyphony[i]; - } - - printf("SET_POLYPHONY(%d, %d) for a total of %d voices\n", midi_channel, buf[2], voices); - printf("[iterator] DEBUG: Polyphony = [ "); - for (i = 0; i < self1->_numChannels; i++) - printf("%d ", _polyphony[i]); - printf("]\n"); - printf("[iterator] DEBUG: Importance = [ "); - printf("]\n"); - } -#endif - break; - - case SCI_MIDI_SET_REVERB: - break; - - case SCI_MIDI_CHANNEL_MUTE: - warning("CHANNEL_MUTE(%d, %d)", midi_channel, buf[2]); - break; - - case SCI_MIDI_HOLD: { - // Safe cast: This controller is only used in SCI1 - Sci1SongIterator *self1 = (Sci1SongIterator *)this; - - if (buf[2] == self1->_hold) { - channel->offset = channel->initial_offset; - channel->state = SI_STATE_COMMAND; - channel->total_timepos = 0; - - self1->_numLoopedChannels = self1->_numActiveChannels - 1; - - // FIXME: - // This implementation of hold breaks getting out of the - // limo when visiting the airport near the start of LSL5. - // It seems like all channels should be reset here somehow, - // but not sure how. - // Forcing all channel offsets to 0 seems to fix the hang, - // but somehow slows the exit sequence down to take 20 seconds - // instead of about 3. - - return SI_LOOP; - } - - break; - } - case 0x04: /* UNKNOWN NYI (happens in LSL2 gameshow) */ - case 0x46: /* UNKNOWN NYI (happens in LSL3 binoculars) */ - case 0x61: /* UNKNOWN NYI (special for AdLib? Iceman) */ - case 0x73: /* UNKNOWN NYI (happens in Hoyle) */ - case 0xd1: /* UNKNOWN NYI (happens in KQ4 when riding the unicorn) */ - return /* Execute next command */ - nextCommand(buf, result); - - case 0x01: /* modulation */ - case 0x07: /* volume */ - case 0x0a: /* panpot */ - case 0x0b: /* expression */ - case 0x40: /* hold */ - case 0x79: /* reset all */ - /* No special treatment neccessary */ - break; - - } - return 0; - - } else { -#if 0 - /* Perform remapping, if neccessary */ - if (cmd != SCI_MIDI_SET_SIGNAL - && cmd < 0xf0) { /* Not a generic command */ - int chan = cmd & 0xf; - int op = cmd & 0xf0; - - chan = channel_remap[chan]; - buf[0] = chan | op; - } -#endif - - /* Process as normal MIDI operation */ - return 0; - } -} - -int BaseSongIterator::processMidi(byte *buf, int *result, - SongIteratorChannel *channel, int flags) { - CHECK_FOR_END(0); - - switch (channel->state) { - - case SI_STATE_PCM: { - if (_data[channel->offset] == 0 - && _data[channel->offset + 1] == SCI_MIDI_EOT) - /* Fake one extra tick to trick the interpreter into not killing the song iterator right away */ - channel->state = SI_STATE_PCM_MAGIC_DELTA; - else - channel->state = SI_STATE_DELTA_TIME; - return SI_PCM; - } - - case SI_STATE_PCM_MAGIC_DELTA: { - int rate; - int offset; - uint size; - int delay; - if (_sci0_get_pcm_data((Sci0SongIterator *)this, &rate, &offset, &size)) - return SI_FINISHED; /* 'tis broken */ - channel->state = SI_STATE_FINISHED; - delay = (size * 50 + rate - 1) / rate; /* number of ticks to completion*/ - - debugC(2, kDebugLevelSound, "delaying %d ticks", delay); - return delay; - } - - case SI_STATE_UNINITIALISED: - warning("Attempt to read command from uninitialized iterator"); - init(); - return nextCommand(buf, result); - - case SI_STATE_FINISHED: - return SI_FINISHED; - - case SI_STATE_DELTA_TIME: { - int offset; - int ticks = _parse_ticks(_data.begin() + channel->offset, - &offset, - _data.size() - channel->offset); - - channel->offset += offset; - channel->delay += ticks; - channel->timepos_increment = ticks; - - CHECK_FOR_END(0); - - channel->state = SI_STATE_COMMAND; - - if (ticks) - return ticks; - } - - /* continute otherwise... */ - - case SI_STATE_COMMAND: { - int retval; - channel->total_timepos += channel->timepos_increment; - channel->timepos_increment = 0; - - retval = parseMidiCommand(buf, result, channel, flags); - - if (retval == SI_FINISHED) { - if (_numActiveChannels) - --(_numActiveChannels); -#ifdef DEBUG_DECODING - fprintf(stderr, "%s L%d: (%p):%d Finished channel, %d channels left\n", - __FILE__, __LINE__, this, channel->id, - _numActiveChannels); -#endif - /* If we still have channels left... */ - if (_numActiveChannels) { - return nextCommand(buf, result); - } - - /* Otherwise, we have reached the end */ - _loops = 0; - } - - return retval; - } - - default: - error("Invalid iterator state %d", channel->state); - return SI_FINISHED; - } -} - -int Sci0SongIterator::nextCommand(byte *buf, int *result) { - return processMidi(buf, result, &_channel, PARSE_FLAG_PARAMETRIC_CUE); -} - -static int _sci0_header_magic_p(byte *data, int offset, int size) { - if (offset + 0x10 > size) - return 0; - return (data[offset] == 0x1a) - && (data[offset + 1] == 0x00) - && (data[offset + 2] == 0x01) - && (data[offset + 3] == 0x00); -} - - -static int _sci0_get_pcm_data(Sci0SongIterator *self, - int *rate, int *xoffset, uint *xsize) { - int tries = 2; - bool found_it = false; - byte *pcm_data; - int size; - uint offset = SCI0_MIDI_OFFSET; - - if (self->_data[0] != 2) - return 1; - /* No such luck */ - - while ((tries--) && (offset < self->_data.size()) && (!found_it)) { - // Search through the garbage manually - // FIXME: Replace offset by an iterator - Common::Array<byte>::iterator iter = Common::find(self->_data.begin() + offset, self->_data.end(), SCI0_END_OF_SONG); - - if (iter == self->_data.end()) { - warning("Playing unterminated song"); - return 1; - } - - // add one to move it past the END_OF_SONG marker - iter++; - offset = iter - self->_data.begin(); // FIXME - - - if (_sci0_header_magic_p(self->_data.begin(), offset, self->_data.size())) - found_it = true; - } - - if (!found_it) { - warning("Song indicates presence of PCM, but" - " none found (finally at offset %04x)", offset); - - return 1; - } - - pcm_data = self->_data.begin() + offset; - - size = READ_LE_UINT16(pcm_data + SCI0_PCM_SIZE_OFFSET); - - /* Two of the format parameters are fixed by design: */ - *rate = READ_LE_UINT16(pcm_data + SCI0_PCM_SAMPLE_RATE_OFFSET); - - if (offset + SCI0_PCM_DATA_OFFSET + size != self->_data.size()) { - int d = offset + SCI0_PCM_DATA_OFFSET + size - self->_data.size(); - - warning("PCM advertizes %d bytes of data, but %d" - " bytes are trailing in the resource", - size, self->_data.size() - (offset + SCI0_PCM_DATA_OFFSET)); - - if (d > 0) - size -= d; /* Fix this */ - } - - *xoffset = offset; - *xsize = size; - - return 0; -} - -static Audio::AudioStream *makeStream(byte *data, int size, int rate) { - debugC(2, kDebugLevelSound, "Playing PCM data of size %d, rate %d", size, rate); - - // Duplicate the data - byte *sound = (byte *)malloc(size); - memcpy(sound, data, size); - - // Convert stream format flags - int flags = Audio::FLAG_UNSIGNED; - return Audio::makeRawStream(sound, size, rate, flags); -} - -Audio::AudioStream *Sci0SongIterator::getAudioStream() { - int rate; - int offset; - uint size; - if (_sci0_get_pcm_data(this, &rate, &offset, &size)) - return NULL; - - _channel.state = SI_STATE_FINISHED; /* Don't play both PCM and music */ - - return makeStream(_data.begin() + offset + SCI0_PCM_DATA_OFFSET, size, rate); -} - -SongIterator *Sci0SongIterator::handleMessage(Message msg) { - if (msg._class == _SIMSG_BASE) { - switch (msg._type) { - - case _SIMSG_BASEMSG_PRINT: - print_tabs_id(msg._arg.i, ID); - debugC(2, kDebugLevelSound, "SCI0: dev=%d, active-chan=%d, size=%d, loops=%d", - _deviceId, _numActiveChannels, _data.size(), _loops); - break; - - case _SIMSG_BASEMSG_SET_LOOPS: - _loops = msg._arg.i; - break; - - case _SIMSG_BASEMSG_STOP: { - songit_id_t sought_id = msg.ID; - - if (sought_id == ID) - _channel.state = SI_STATE_FINISHED; - break; - } - - case _SIMSG_BASEMSG_SET_PLAYMASK: { - int i; - _deviceId = msg._arg.i; - - /* Set all but the rhytm channel mask bits */ - _channel.playmask &= ~(1 << MIDI_RHYTHM_CHANNEL); - - for (i = 0; i < MIDI_CHANNELS; i++) - if (_data[2 + (i << 1)] & _deviceId - && i != MIDI_RHYTHM_CHANNEL) - _channel.playmask |= (1 << i); - } - break; - - case _SIMSG_BASEMSG_SET_RHYTHM: - _channel.playmask &= ~(1 << MIDI_RHYTHM_CHANNEL); - if (msg._arg.i) - _channel.playmask |= (1 << MIDI_RHYTHM_CHANNEL); - break; - - case _SIMSG_BASEMSG_SET_FADE: { - fade_params_t *fp = (fade_params_t *) msg._arg.p; - fade.action = fp->action; - fade.final_volume = fp->final_volume; - fade.ticks_per_step = fp->ticks_per_step; - fade.step_size = fp->step_size; - break; - } - - default: - return NULL; - } - - return this; - } - return NULL; -} - -int Sci0SongIterator::getTimepos() { - return _channel.total_timepos; -} - -Sci0SongIterator::Sci0SongIterator(byte *data, uint size, songit_id_t id) - : BaseSongIterator(data, size, id) { - channel_mask = 0xffff; // Allocate all channels by default - _channel.state = SI_STATE_UNINITIALISED; - - for (int i = 0; i < MIDI_CHANNELS; i++) - _polyphony[i] = data[1 + (i << 1)]; - - init(); -} - -void Sci0SongIterator::init() { - fade.action = FADE_ACTION_NONE; - _resetflag = 0; - _loops = 0; - priority = 0; - - _ccc = 0; /* Reset cumulative cue counter */ - _numActiveChannels = 1; - _channel.init(0, SCI0_MIDI_OFFSET, _data.size()); - _channel.resetSynthChannels(); - - if (_data[0] == 2) /* Do we have an embedded PCM? */ - _channel.state = SI_STATE_PCM; -} - -SongIterator *Sci0SongIterator::clone(int delta) { - Sci0SongIterator *newit = new Sci0SongIterator(*this); - return newit; -} - - -/***************************/ -/*-- SCI1 song iterators --*/ -/***************************/ - -int Sci1SongIterator::initSample(const int offset) { - Sci1Sample sample; - int rate; - int length; - int begin; - int end; - - CHECK_FOR_END_ABSOLUTE((uint)offset + 10); - if (_data[offset + 1] != 0) - warning("[iterator-1] In sample at offset 0x04x: Byte #1 is %02x instead of zero", - _data[offset + 1]); - - rate = (int16)READ_LE_UINT16(_data.begin() + offset + 2); - length = READ_LE_UINT16(_data.begin() + offset + 4); - begin = (int16)READ_LE_UINT16(_data.begin() + offset + 6); - end = (int16)READ_LE_UINT16(_data.begin() + offset + 8); - - CHECK_FOR_END_ABSOLUTE((uint)(offset + 10 + length)); - - sample.delta = begin; - sample.size = length; - sample._data = _data.begin() + offset + 10; - -#ifdef DEBUG_VERBOSE - fprintf(stderr, "[SAMPLE] %x/%x/%x/%x l=%x\n", - offset + 10, begin, end, _data.size(), length); -#endif - - sample.rate = rate; - - sample.announced = false; - - /* Insert into the sample list at the right spot, keeping it sorted by delta */ - Common::List<Sci1Sample>::iterator seeker = _samples.begin(); - while (seeker != _samples.end() && seeker->delta < begin) - ++seeker; - _samples.insert(seeker, sample); - - return 0; /* Everything's fine */ -} - -int Sci1SongIterator::initSong() { - int last_time; - uint offset = 0; - _numChannels = 0; - _samples.clear(); -// _deviceId = 0x0c; - - if (_data[offset] == 0xf0) { - priority = _data[offset + 1]; - - offset += 8; - } - - while (_data[offset] != 0xff - && _data[offset] != _deviceId) { - offset++; - CHECK_FOR_END_ABSOLUTE(offset + 1); - while (_data[offset] != 0xff) { - CHECK_FOR_END_ABSOLUTE(offset + 7); - offset += 6; - } - offset++; - } - - if (_data[offset] == 0xff) { - warning("[iterator] Song does not support hardware 0x%02x", _deviceId); - return 1; - } - - offset++; - - while (_data[offset] != 0xff) { /* End of list? */ - uint track_offset; - int end; - offset += 2; - - CHECK_FOR_END_ABSOLUTE(offset + 4); - - track_offset = READ_LE_UINT16(_data.begin() + offset); - end = READ_LE_UINT16(_data.begin() + offset + 2); - - CHECK_FOR_END_ABSOLUTE(track_offset - 1); - - if (_data[track_offset] == 0xfe) { - if (initSample(track_offset)) - return 1; /* Error */ - } else { - /* Regular MIDI channel */ - if (_numChannels >= MIDI_CHANNELS) { - warning("[iterator] Song has more than %d channels, cutting them off", - MIDI_CHANNELS); - break; /* Scan for remaining samples */ - } else { - int channel_nr = _data[track_offset] & 0xf; - SongIteratorChannel &channel = _channels[_numChannels++]; - - /* - if (_data[track_offset] & 0xf0) - printf("Channel %d has mapping bits %02x\n", - channel_nr, _data[track_offset] & 0xf0); - */ - - // Add 2 to skip over header bytes */ - channel.init(channel_nr, track_offset + 2, track_offset + end); - channel.resetSynthChannels(); - - _polyphony[_numChannels - 1] = _data[channel.offset - 1] & 15; - - channel.playmask = ~0; /* Enable all */ - channel_mask |= (1 << channel_nr); - - CHECK_FOR_END_ABSOLUTE(offset + end); - } - } - offset += 4; - CHECK_FOR_END_ABSOLUTE(offset); - } - - /* Now ensure that sample deltas are relative to the previous sample */ - last_time = 0; - _numActiveChannels = _numChannels; - _numLoopedChannels = 0; - - for (Common::List<Sci1Sample>::iterator seeker = _samples.begin(); - seeker != _samples.end(); ++seeker) { - int prev_last_time = last_time; - //printf("[iterator] Detected sample: %d Hz, %d bytes at time %d\n", - // seeker->format.rate, seeker->size, seeker->delta); - last_time = seeker->delta; - seeker->delta -= prev_last_time; - } - - return 0; /* Success */ -} - -int Sci1SongIterator::getSmallestDelta() const { - int d = -1; - for (int i = 0; i < _numChannels; i++) - if (_channels[i].state == SI_STATE_COMMAND - && (d == -1 || _channels[i].delay < d)) - d = _channels[i].delay; - - if (!_samples.empty() && _samples.begin()->delta < d) - return _samples.begin()->delta; - else - return d; -} - -void Sci1SongIterator::updateDelta(int delta) { - if (!_samples.empty()) - _samples.begin()->delta -= delta; - - for (int i = 0; i < _numChannels; i++) - if (_channels[i].state == SI_STATE_COMMAND) - _channels[i].delay -= delta; -} - -bool Sci1SongIterator::noDeltaTime() const { - for (int i = 0; i < _numChannels; i++) - if (_channels[i].state == SI_STATE_DELTA_TIME) - return false; - return true; -} - -#define COMMAND_INDEX_NONE -1 -#define COMMAND_INDEX_PCM -2 - -int Sci1SongIterator::getCommandIndex() const { - /* Determine the channel # of the next active event, or -1 */ - int i; - int base_delay = 0x7ffffff; - int best_chan = COMMAND_INDEX_NONE; - - for (i = 0; i < _numChannels; i++) - if ((_channels[i].state != SI_STATE_PENDING) - && (_channels[i].state != SI_STATE_FINISHED)) { - - if ((_channels[i].state == SI_STATE_DELTA_TIME) - && (_channels[i].delay == 0)) - return i; - /* First, read all unknown delta times */ - - if (_channels[i].delay < base_delay) { - best_chan = i; - base_delay = _channels[i].delay; - } - } - - if (!_samples.empty() && base_delay >= _samples.begin()->delta) - return COMMAND_INDEX_PCM; - - return best_chan; -} - - -Audio::AudioStream *Sci1SongIterator::getAudioStream() { - Common::List<Sci1Sample>::iterator sample = _samples.begin(); - if (sample != _samples.end() && sample->delta <= 0) { - Audio::AudioStream *feed = makeStream(sample->_data, sample->size, sample->rate); - _samples.erase(sample); - - return feed; - } else - return NULL; -} - -int Sci1SongIterator::nextCommand(byte *buf, int *result) { - - if (!_initialised) { - //printf("[iterator] DEBUG: Initialising for %d\n", _deviceId); - _initialised = true; - if (initSong()) - return SI_FINISHED; - } - - - if (_delayRemaining) { - int delay = _delayRemaining; - _delayRemaining = 0; - return delay; - } - - int retval = 0; - do { /* All delays must be processed separately */ - int chan = getCommandIndex(); - - if (chan == COMMAND_INDEX_NONE) { - return SI_FINISHED; - } - - if (chan == COMMAND_INDEX_PCM) { - - if (_samples.begin()->announced) { - /* Already announced; let's discard it */ - Audio::AudioStream *feed = getAudioStream(); - delete feed; - } else { - int delay = _samples.begin()->delta; - - if (delay) { - updateDelta(delay); - return delay; - } - /* otherwise we're touching a PCM */ - _samples.begin()->announced = true; - return SI_PCM; - } - } else { /* Not a PCM */ - - retval = processMidi(buf, result, - &(_channels[chan]), - PARSE_FLAG_LOOPS_UNLIMITED); - - if (retval == SI_LOOP) { - _numLoopedChannels++; - _channels[chan].state = SI_STATE_PENDING; - _channels[chan].delay = 0; - - if (_numLoopedChannels == _numActiveChannels) { - int i; - - /* Everyone's ready: Let's loop */ - for (i = 0; i < _numChannels; i++) - if (_channels[i].state == SI_STATE_PENDING) - _channels[i].state = SI_STATE_DELTA_TIME; - - _numLoopedChannels = 0; - return SI_LOOP; - } - } else if (retval == SI_FINISHED) { -#ifdef DEBUG - fprintf(stderr, "FINISHED some channel\n"); -#endif - } else if (retval > 0) { - int sd ; - sd = getSmallestDelta(); - - if (noDeltaTime() && sd) { - /* No other channel is ready */ - updateDelta(sd); - - /* Only from here do we return delta times */ - return sd; - } - } - - } /* Not a PCM */ - - } while (retval > 0); - - return retval; -} - -SongIterator *Sci1SongIterator::handleMessage(Message msg) { - if (msg._class == _SIMSG_BASE) { /* May extend this in the future */ - switch (msg._type) { - - case _SIMSG_BASEMSG_PRINT: { - int playmask = 0; - int i; - - for (i = 0; i < _numChannels; i++) - playmask |= _channels[i].playmask; - - print_tabs_id(msg._arg.i, ID); - debugC(2, kDebugLevelSound, "SCI1: chan-nr=%d, playmask=%04x", - _numChannels, playmask); - } - break; - - case _SIMSG_BASEMSG_STOP: { - songit_id_t sought_id = msg.ID; - int i; - - if (sought_id == ID) { - ID = 0; - - for (i = 0; i < _numChannels; i++) - _channels[i].state = SI_STATE_FINISHED; - } - break; - } - - case _SIMSG_BASEMSG_SET_PLAYMASK: - if (msg.ID == ID) { - channel_mask = 0; - - _deviceId = msg._arg.i; - - if (_initialised) { - int i; - int toffset = -1; - - for (i = 0; i < _numChannels; i++) - if (_channels[i].state != SI_STATE_FINISHED - && _channels[i].total_timepos > toffset) { - toffset = _channels[i].total_timepos - + _channels[i].timepos_increment - - _channels[i].delay; - } - - /* Find an active channel so that we can - ** get the correct time offset */ - - initSong(); - - toffset -= _delayRemaining; - _delayRemaining = 0; - - if (toffset > 0) - return new_fast_forward_iterator(this, toffset); - } else { - initSong(); - _initialised = true; - } - - break; - - } - - case _SIMSG_BASEMSG_SET_LOOPS: - if (msg.ID == ID) - _loops = (msg._arg.i > 32767) ? 99 : 0; - /* 99 is arbitrary, but we can't use '1' because of - ** the way we're testing in the decoding section. */ - break; - - case _SIMSG_BASEMSG_SET_HOLD: - _hold = msg._arg.i; - break; - case _SIMSG_BASEMSG_SET_RHYTHM: - /* Ignore */ - break; - - case _SIMSG_BASEMSG_SET_FADE: { - fade_params_t *fp = (fade_params_t *) msg._arg.p; - fade.action = fp->action; - fade.final_volume = fp->final_volume; - fade.ticks_per_step = fp->ticks_per_step; - fade.step_size = fp->step_size; - break; - } - - default: - warning("Unsupported command %d to SCI1 iterator", msg._type); - } - return this; - } - return NULL; -} - -Sci1SongIterator::Sci1SongIterator(byte *data, uint size, songit_id_t id) - : BaseSongIterator(data, size, id) { - channel_mask = 0; // Defer channel allocation - - for (int i = 0; i < MIDI_CHANNELS; i++) - _polyphony[i] = 0; // Unknown - - init(); -} - -void Sci1SongIterator::init() { - fade.action = FADE_ACTION_NONE; - _resetflag = 0; - _loops = 0; - priority = 0; - - _ccc = 0; - _deviceId = 0x00; // Default to Sound Blaster/AdLib for purposes of cue computation - _numChannels = 0; - _initialised = false; - _delayRemaining = 0; - _loops = 0; - _hold = 0; - memset(_polyphony, 0, sizeof(_polyphony)); -} - -Sci1SongIterator::~Sci1SongIterator() { -} - - -SongIterator *Sci1SongIterator::clone(int delta) { - Sci1SongIterator *newit = new Sci1SongIterator(*this); - newit->_delayRemaining = delta; - return newit; -} - -int Sci1SongIterator::getTimepos() { - int max = 0; - int i; - - for (i = 0; i < _numChannels; i++) - if (_channels[i].total_timepos > max) - max = _channels[i].total_timepos; - - return max; -} - -/** - * A song iterator with the purpose of sending notes-off channel commands. - */ -class CleanupSongIterator : public SongIterator { -public: - CleanupSongIterator(uint channels) { - channel_mask = channels; - ID = 17; - } - - int nextCommand(byte *buf, int *result); - Audio::AudioStream *getAudioStream() { return NULL; } - SongIterator *handleMessage(Message msg); - int getTimepos() { return 0; } - SongIterator *clone(int delta) { return new CleanupSongIterator(*this); } -}; - -SongIterator *CleanupSongIterator::handleMessage(Message msg) { - if (msg._class == _SIMSG_BASEMSG_PRINT && msg._type == _SIMSG_BASEMSG_PRINT) { - print_tabs_id(msg._arg.i, ID); - debugC(2, kDebugLevelSound, "CLEANUP"); - } - - return NULL; -} - -int CleanupSongIterator::nextCommand(byte *buf, int *result) { - /* Task: Return channel-notes-off for each channel */ - if (channel_mask) { - int bs = sci_ffs(channel_mask) - 1; - - channel_mask &= ~(1 << bs); - buf[0] = 0xb0 | bs; /* Controller */ - buf[1] = SCI_MIDI_CHANNEL_NOTES_OFF; - buf[2] = 0; /* Hmm... */ - *result = 3; - return 0; - } else - return SI_FINISHED; -} - -/**********************/ -/*-- Timer iterator --*/ -/**********************/ -int TimerSongIterator::nextCommand(byte *buf, int *result) { - if (_delta) { - int d = _delta; - _delta = 0; - return d; - } - return SI_FINISHED; -} - -SongIterator *new_timer_iterator(int delta) { - return new TimerSongIterator(delta); -} - -/**********************************/ -/*-- Fast-forward song iterator --*/ -/**********************************/ - -int FastForwardSongIterator::nextCommand(byte *buf, int *result) { - if (_delta <= 0) - return SI_MORPH; /* Did our duty */ - - while (1) { - int rv = _delegate->nextCommand(buf, result); - - if (rv > 0) { - /* Subtract from the delta we want to wait */ - _delta -= rv; - - /* Done */ - if (_delta < 0) - return -_delta; - } - - if (rv <= 0) - return rv; - } -} - -Audio::AudioStream *FastForwardSongIterator::getAudioStream() { - return _delegate->getAudioStream(); -} - -SongIterator *FastForwardSongIterator::handleMessage(Message msg) { - if (msg._class == _SIMSG_PLASTICWRAP) { - assert(msg._type == _SIMSG_PLASTICWRAP_ACK_MORPH); - - if (_delta <= 0) { - SongIterator *it = _delegate; - delete this; - return it; - } - - warning("[ff-iterator] Morphing without need"); - return this; - } - - if (msg._class == _SIMSG_BASE && msg._type == _SIMSG_BASEMSG_PRINT) { - print_tabs_id(msg._arg.i, ID); - debugC(2, kDebugLevelSound, "FASTFORWARD:"); - msg._arg.i++; - } - - // And continue with the delegate - songit_handle_message(&_delegate, msg); - - return NULL; -} - - -int FastForwardSongIterator::getTimepos() { - return _delegate->getTimepos(); -} - -FastForwardSongIterator::FastForwardSongIterator(SongIterator *capsit, int delta) - : _delegate(capsit), _delta(delta) { - - channel_mask = capsit->channel_mask; -} - -SongIterator *FastForwardSongIterator::clone(int delta) { - FastForwardSongIterator *newit = new FastForwardSongIterator(*this); - newit->_delegate = _delegate->clone(delta); - return newit; -} - -SongIterator *new_fast_forward_iterator(SongIterator *capsit, int delta) { - if (capsit == NULL) - return NULL; - - FastForwardSongIterator *it = new FastForwardSongIterator(capsit, delta); - return it; -} - - -/********************/ -/*-- Tee iterator --*/ -/********************/ - - -static void song_iterator_add_death_listener(SongIterator *it, TeeSongIterator *client) { - for (int i = 0; i < SONGIT_MAX_LISTENERS; ++i) { - if (it->_deathListeners[i] == 0) { - it->_deathListeners[i] = client; - return; - } - } - error("FATAL: Too many death listeners for song iterator"); -} - -static void song_iterator_remove_death_listener(SongIterator *it, TeeSongIterator *client) { - for (int i = 0; i < SONGIT_MAX_LISTENERS; ++i) { - if (it->_deathListeners[i] == client) { - it->_deathListeners[i] = 0; - return; - } - } -} - -static void song_iterator_transfer_death_listeners(SongIterator *it, SongIterator *it_from) { - for (int i = 0; i < SONGIT_MAX_LISTENERS; ++i) { - if (it_from->_deathListeners[i]) - song_iterator_add_death_listener(it, it_from->_deathListeners[i]); - it_from->_deathListeners[i] = 0; - } -} - -static void songit_tee_death_notification(TeeSongIterator *self, SongIterator *corpse) { - if (corpse == self->_children[TEE_LEFT].it) { - self->_status &= ~TEE_LEFT_ACTIVE; - self->_children[TEE_LEFT].it = NULL; - } else if (corpse == self->_children[TEE_RIGHT].it) { - self->_status &= ~TEE_RIGHT_ACTIVE; - self->_children[TEE_RIGHT].it = NULL; - } else { - error("songit_tee_death_notification() failed: Breakpoint in %s, line %d", __FILE__, __LINE__); - } -} - -TeeSongIterator::TeeSongIterator(SongIterator *left, SongIterator *right) { - int i; - int firstfree = 1; /* First free channel */ - int incomplete_map = 0; - - _readyToMorph = false; - _status = TEE_LEFT_ACTIVE | TEE_RIGHT_ACTIVE; - - _children[TEE_LEFT].it = left; - _children[TEE_RIGHT].it = right; - - /* Default to lhs channels */ - channel_mask = left->channel_mask; - for (i = 0; i < 16; i++) - if (channel_mask & (1 << i) & right->channel_mask - && (i != MIDI_RHYTHM_CHANNEL) /* Share rhythm */) { /*conflict*/ - while ((firstfree == MIDI_RHYTHM_CHANNEL) - /* Either if it's the rhythm channel or if it's taken */ - || (firstfree < MIDI_CHANNELS - && ((1 << firstfree) & channel_mask))) - ++firstfree; - - if (firstfree == MIDI_CHANNELS) { - incomplete_map = 1; - //warning("[songit-tee <%08lx,%08lx>] Could not remap right channel #%d: Out of channels", - // left->ID, right->ID, i); - } else { - _children[TEE_RIGHT].it->channel_remap[i] = firstfree; - - channel_mask |= (1 << firstfree); - } - } -#ifdef DEBUG_TEE_ITERATOR - if (incomplete_map) { - int c; - fprintf(stderr, "[songit-tee <%08lx,%08lx>] Channels:" - " %04x <- %04x | %04x\n", - left->ID, right->ID, - channel_mask, - left->channel_mask, right->channel_mask); - for (c = 0 ; c < 2; c++) - for (i = 0 ; i < 16; i++) - fprintf(stderr, " map [%d][%d] -> %d\n", - c, i, _children[c].it->channel_remap[i]); - } -#endif - - - song_iterator_add_death_listener(left, this); - song_iterator_add_death_listener(right, this); -} - -TeeSongIterator::~TeeSongIterator() { - // When we die, remove any listeners from our children - if (_children[TEE_LEFT].it) { - song_iterator_remove_death_listener(_children[TEE_LEFT].it, this); - } - - if (_children[TEE_RIGHT].it) { - song_iterator_remove_death_listener(_children[TEE_RIGHT].it, this); - } -} - - -int TeeSongIterator::nextCommand(byte *buf, int *result) { - static const int ready_masks[2] = {TEE_LEFT_READY, TEE_RIGHT_READY}; - static const int active_masks[2] = {TEE_LEFT_ACTIVE, TEE_RIGHT_ACTIVE}; - static const int pcm_masks[2] = {TEE_LEFT_PCM, TEE_RIGHT_PCM}; - int i; - int retid; - -#ifdef DEBUG_TEE_ITERATOR - fprintf(stderr, "[Tee] %02x\n", _status); -#endif - - if (!(_status & (TEE_LEFT_ACTIVE | TEE_RIGHT_ACTIVE))) - /* None is active? */ - return SI_FINISHED; - - if (_readyToMorph) - return SI_MORPH; - - if ((_status & (TEE_LEFT_ACTIVE | TEE_RIGHT_ACTIVE)) - != (TEE_LEFT_ACTIVE | TEE_RIGHT_ACTIVE)) { - /* Not all are is active? */ - int which = 0; -#ifdef DEBUG_TEE_ITERATOR - fprintf(stderr, "\tRequesting transformation...\n"); -#endif - if (_status & TEE_LEFT_ACTIVE) - which = TEE_LEFT; - else if (_status & TEE_RIGHT_ACTIVE) - which = TEE_RIGHT; - memcpy(buf, _children[which].buf, sizeof(buf)); - *result = _children[which].result; - _readyToMorph = true; - return _children[which].retval; - } - - /* First, check for unreported PCMs */ - for (i = TEE_LEFT; i <= TEE_RIGHT; i++) - if ((_status & (ready_masks[i] | pcm_masks[i])) - == (ready_masks[i] | pcm_masks[i])) { - _status &= ~ready_masks[i]; - return SI_PCM; - } - - for (i = TEE_LEFT; i <= TEE_RIGHT; i++) - if (!(_status & ready_masks[i])) { - - /* Buffers aren't ready yet */ - _children[i].retval = - songit_next(&(_children[i].it), - _children[i].buf, - &(_children[i].result), - IT_READER_MASK_ALL - | IT_READER_MAY_FREE - | IT_READER_MAY_CLEAN); - - _status |= ready_masks[i]; -#ifdef DEBUG_TEE_ITERATOR - fprintf(stderr, "\t Must check %d: %d\n", i, _children[i].retval); -#endif - - if (_children[i].retval == SI_ABSOLUTE_CUE || - _children[i].retval == SI_RELATIVE_CUE) - return _children[i].retval; - if (_children[i].retval == SI_FINISHED) { - _status &= ~active_masks[i]; - /* Recurse to complete */ -#ifdef DEBUG_TEE_ITERATOR - fprintf(stderr, "\t Child %d signalled completion, recursing w/ status %02x\n", i, _status); -#endif - return nextCommand(buf, result); - } else if (_children[i].retval == SI_PCM) { - _status |= pcm_masks[i]; - _status &= ~ready_masks[i]; - return SI_PCM; - } - } - - - /* We've already handled PCM, MORPH and FINISHED, CUEs & LOOP remain */ - - retid = TEE_LEFT; - if ((_children[TEE_LEFT].retval > 0) - /* Asked to delay */ - && (_children[TEE_RIGHT].retval <= _children[TEE_LEFT].retval)) - /* Is not delaying or not delaying as much */ - retid = TEE_RIGHT; - -#ifdef DEBUG_TEE_ITERATOR - fprintf(stderr, "\tl:%d / r:%d / chose %d\n", - _children[TEE_LEFT].retval, _children[TEE_RIGHT].retval, retid); -#endif - - /* Adjust delta times */ - if (_children[retid].retval > 0 - && _children[1-retid].retval > 0) { - if (_children[1-retid].retval - == _children[retid].retval) - /* If both _children wait the same amount of time, - ** we have to re-fetch commands from both */ - _status &= ~ready_masks[1-retid]; - else - /* If they don't, we can/must re-use the other - ** child's delay time */ - _children[1-retid].retval - -= _children[retid].retval; - } - - _status &= ~ready_masks[retid]; - memcpy(buf, _children[retid].buf, sizeof(buf)); - *result = _children[retid].result; - - return _children[retid].retval; -} - -Audio::AudioStream *TeeSongIterator::getAudioStream() { - static const int pcm_masks[2] = {TEE_LEFT_PCM, TEE_RIGHT_PCM}; - int i; - - for (i = TEE_LEFT; i <= TEE_RIGHT; i++) - if (_status & pcm_masks[i]) { - _status &= ~pcm_masks[i]; - return _children[i].it->getAudioStream(); - } - - return NULL; // No iterator -} - -SongIterator *TeeSongIterator::handleMessage(Message msg) { - if (msg._class == _SIMSG_PLASTICWRAP) { - assert(msg._type == _SIMSG_PLASTICWRAP_ACK_MORPH); - - SongIterator *old_it; - if (!(_status & (TEE_LEFT_ACTIVE | TEE_RIGHT_ACTIVE))) { - delete this; - return NULL; - } else if (!(_status & TEE_LEFT_ACTIVE)) { - delete _children[TEE_LEFT].it; - _children[TEE_LEFT].it = 0; - old_it = _children[TEE_RIGHT].it; - song_iterator_remove_death_listener(old_it, this); - song_iterator_transfer_death_listeners(old_it, this); - delete this; - return old_it; - } else if (!(_status & TEE_RIGHT_ACTIVE)) { - delete _children[TEE_RIGHT].it; - _children[TEE_RIGHT].it = 0; - old_it = _children[TEE_LEFT].it; - song_iterator_remove_death_listener(old_it, this); - song_iterator_transfer_death_listeners(old_it, this); - delete this; - return old_it; - } - - warning("[tee-iterator] Morphing without need"); - return this; - } - - if (msg._class == _SIMSG_BASE && msg._type == _SIMSG_BASEMSG_PRINT) { - print_tabs_id(msg._arg.i, ID); - debugC(2, kDebugLevelSound, "TEE:"); - msg._arg.i++; - } - - // And continue with the children - if (_children[TEE_LEFT].it) - songit_handle_message(&(_children[TEE_LEFT].it), msg); - if (_children[TEE_RIGHT].it) - songit_handle_message(&(_children[TEE_RIGHT].it), msg); - - return NULL; -} - -void TeeSongIterator::init() { - _status = TEE_LEFT_ACTIVE | TEE_RIGHT_ACTIVE; - _children[TEE_LEFT].it->init(); - _children[TEE_RIGHT].it->init(); -} - -SongIterator *TeeSongIterator::clone(int delta) { - TeeSongIterator *newit = new TeeSongIterator(*this); - - if (_children[TEE_LEFT].it) - newit->_children[TEE_LEFT].it = _children[TEE_LEFT].it->clone(delta); - if (_children[TEE_RIGHT].it) - newit->_children[TEE_RIGHT].it = _children[TEE_RIGHT].it->clone(delta); - - return newit; -} - - -/*************************************/ -/*-- General purpose functionality --*/ -/*************************************/ - -int songit_next(SongIterator **it, byte *buf, int *result, int mask) { - int retval; - - if (!*it) - return SI_FINISHED; - - do { - retval = (*it)->nextCommand(buf, result); - if (retval == SI_MORPH) { - debugC(2, kDebugLevelSound, " Morphing %p (stored at %p)", (void *)*it, (void *)it); - if (!SIMSG_SEND((*it), SIMSG_ACK_MORPH)) { - error("SI_MORPH failed. Breakpoint in %s, line %d", __FILE__, __LINE__); - } else - debugC(2, kDebugLevelSound, "SI_MORPH successful"); - } - - if (retval == SI_FINISHED) - debugC(2, kDebugLevelSound, "[song-iterator] Song finished. mask = %04x, cm=%04x", - mask, (*it)->channel_mask); - if (retval == SI_FINISHED - && (mask & IT_READER_MAY_CLEAN) - && (*it)->channel_mask) { /* This last test will fail - ** with a terminated - ** cleanup iterator */ - int channel_mask = (*it)->channel_mask; - - SongIterator *old_it = *it; - *it = new CleanupSongIterator(channel_mask); - for(uint i = 0; i < MIDI_CHANNELS; i++) - (*it)->channel_remap[i] = old_it->channel_remap[i]; - song_iterator_transfer_death_listeners(*it, old_it); - if (mask & IT_READER_MAY_FREE) - delete old_it; - retval = -9999; /* Continue */ - } - } while (!( /* Until one of the following holds */ - (retval > 0 && (mask & IT_READER_MASK_DELAY)) - || (retval == 0 && (mask & IT_READER_MASK_MIDI)) - || (retval == SI_LOOP && (mask & IT_READER_MASK_LOOP)) - || (retval == SI_ABSOLUTE_CUE && - (mask & IT_READER_MASK_CUE)) - || (retval == SI_RELATIVE_CUE && - (mask & IT_READER_MASK_CUE)) - || (retval == SI_PCM && (mask & IT_READER_MASK_PCM)) - || (retval == SI_FINISHED) - )); - - if (retval == SI_FINISHED && (mask & IT_READER_MAY_FREE)) { - delete *it; - *it = NULL; - } - - return retval; -} - -SongIterator::SongIterator() { - ID = 0; - channel_mask = 0; - fade.action = FADE_ACTION_NONE; - priority = 0; - memset(_deathListeners, 0, sizeof(_deathListeners)); - - // By default, don't remap - for (uint i = 0; i < 16; i++) - channel_remap[i] = i; -} - -SongIterator::SongIterator(const SongIterator &si) { - ID = si.ID; - channel_mask = si.channel_mask; - fade = si.fade; - priority = si.priority; - memset(_deathListeners, 0, sizeof(_deathListeners)); - - for (uint i = 0; i < 16; i++) - channel_remap[i] = si.channel_remap[i]; -} - - -SongIterator::~SongIterator() { - for (int i = 0; i < SONGIT_MAX_LISTENERS; ++i) - if (_deathListeners[i]) - songit_tee_death_notification(_deathListeners[i], this); -} - -SongIterator *songit_new(byte *data, uint size, SongIteratorType type, songit_id_t id) { - BaseSongIterator *it; - - if (!data || size < 22) { - warning("Attempt to instantiate song iterator for null song data"); - return NULL; - } - - - switch (type) { - case SCI_SONG_ITERATOR_TYPE_SCI0: - it = new Sci0SongIterator(data, size, id); - break; - - case SCI_SONG_ITERATOR_TYPE_SCI1: - it = new Sci1SongIterator(data, size, id); - break; - - default: - /**-- Invalid/unsupported sound resources --**/ - warning("Attempt to instantiate invalid/unknown song iterator type %d", type); - return NULL; - } - - return it; -} - -int songit_handle_message(SongIterator **it_reg_p, SongIterator::Message msg) { - SongIterator *it = *it_reg_p; - SongIterator *newit; - - newit = it->handleMessage(msg); - - if (!newit) - return 0; /* Couldn't handle */ - - *it_reg_p = newit; /* Might have self-morphed */ - return 1; -} - -SongIterator *sfx_iterator_combine(SongIterator *it1, SongIterator *it2) { - if (it1 == NULL) - return it2; - if (it2 == NULL) - return it1; - - /* Both are non-NULL: */ - return new TeeSongIterator(it1, it2); -} - -} // End of namespace Sci - -#endif // USE_OLD_MUSIC_FUNCTIONS diff --git a/engines/sci/sound/iterator/iterator.h b/engines/sci/sound/iterator/iterator.h deleted file mode 100644 index e5c8f50702..0000000000 --- a/engines/sci/sound/iterator/iterator.h +++ /dev/null @@ -1,326 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* Song iterator declarations */ - -#ifndef SCI_SFX_SFX_ITERATOR_H -#define SCI_SFX_SFX_ITERATOR_H - -#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS - -#ifdef USE_OLD_MUSIC_FUNCTIONS -#include "sci/sound/drivers/mididriver.h" - -namespace Audio { - class AudioStream; -} - -namespace Sci { - -enum SongIteratorStatus { - SI_FINISHED = -1, /**< Song finished playing */ - SI_LOOP = -2, /**< Song just looped */ - SI_ABSOLUTE_CUE = -3, /**< Found a song cue (absolute) */ - SI_RELATIVE_CUE = -4, /**< Found a song cue (relative) */ - SI_PCM = -5, /**< Found a PCM */ - SI_IGNORE = -6, /**< This event got edited out by the remapper */ - SI_MORPH = -255 /**< Song iterator requested self-morph. */ -}; - -#define FADE_ACTION_NONE 0 -#define FADE_ACTION_FADE_AND_STOP 1 -#define FADE_ACTION_FADE_AND_CONT 2 - -struct fade_params_t { - int ticks_per_step; - int final_volume; - int step_size; - int action; -}; - -/* Helper defs for messages */ -enum { - _SIMSG_BASE, /* Any base decoder */ - _SIMSG_PLASTICWRAP /* Any "Plastic" (discardable) wrapper decoder */ -}; - -/* Base messages */ -enum { - _SIMSG_BASEMSG_SET_LOOPS, /* Set loops */ - _SIMSG_BASEMSG_SET_PLAYMASK, /* Set the current playmask for filtering */ - _SIMSG_BASEMSG_SET_RHYTHM, /* Activate/deactivate rhythm channel */ - _SIMSG_BASEMSG_ACK_MORPH, /* Acknowledge self-morph */ - _SIMSG_BASEMSG_STOP, /* Stop iterator */ - _SIMSG_BASEMSG_PRINT, /* Print self to stderr, after printing param1 tabs */ - _SIMSG_BASEMSG_SET_HOLD, /* Set value of hold parameter to expect */ - _SIMSG_BASEMSG_SET_FADE /* Set fade parameters */ -}; - -/* "Plastic" (discardable) wrapper messages */ -enum { - _SIMSG_PLASTICWRAP_ACK_MORPH = _SIMSG_BASEMSG_ACK_MORPH /* Acknowledge self-morph */ -}; - -/* Messages */ -#define SIMSG_SET_LOOPS(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_LOOPS,(x) -#define SIMSG_SET_PLAYMASK(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_PLAYMASK,(x) -#define SIMSG_SET_RHYTHM(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_RHYTHM,(x) -#define SIMSG_ACK_MORPH _SIMSG_PLASTICWRAP,_SIMSG_PLASTICWRAP_ACK_MORPH,0 -#define SIMSG_STOP _SIMSG_BASE,_SIMSG_BASEMSG_STOP,0 -#define SIMSG_PRINT(indentation) _SIMSG_BASE,_SIMSG_BASEMSG_PRINT,(indentation) -#define SIMSG_SET_HOLD(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_HOLD,(x) - -/* Message transmission macro: Takes song reference, message reference */ -#define SIMSG_SEND(o, m) songit_handle_message(&(o), SongIterator::Message((o)->ID, m)) -#define SIMSG_SEND_FADE(o, m) songit_handle_message(&(o), SongIterator::Message((o)->ID, _SIMSG_BASE, _SIMSG_BASEMSG_SET_FADE, m)) - -typedef unsigned long songit_id_t; - - -#define SONGIT_MAX_LISTENERS 2 - -class TeeSongIterator; - -class SongIterator { -public: - struct Message { - songit_id_t ID; - uint _class; /* Type of iterator supposed to receive this */ - uint _type; - union { - uint i; - void *p; - } _arg; - - Message() : ID(0), _class(0xFFFF), _type(0xFFFF) {} - - /** - * Create a song iterator message. - * - * @param id: song ID the message is targeted to - * @param recipient_class: Message recipient class - * @param type message type - * @param a argument - * - * @note You should only use this with the SIMSG_* macros - */ - Message(songit_id_t id, int recipient_class, int type, int a) - : ID(id), _class(recipient_class), _type(type) { - _arg.i = a; - } - - /** - * Create a song iterator message, wherein the first parameter is a pointer. - * - * @param id: song ID the message is targeted to - * @param recipient_class: Message recipient class - * @param type message type - * @param a argument - * - * @note You should only use this with the SIMSG_* macros - */ - Message(songit_id_t id, int recipient_class, int type, void *a) - : ID(id), _class(recipient_class), _type(type) { - _arg.p = a; - } - }; - -public: - songit_id_t ID; - uint16 channel_mask; /* Bitmask of all channels this iterator will use */ - fade_params_t fade; - int priority; - - /* Death listeners */ - /* These are not reset during initialisation */ - TeeSongIterator *_deathListeners[SONGIT_MAX_LISTENERS]; - - /* See songit_* for the constructor and non-virtual member functions */ - - byte channel_remap[MIDI_CHANNELS]; ///< Remapping for channels - -public: - SongIterator(); - SongIterator(const SongIterator &); - virtual ~SongIterator(); - - /** - * Resets/initializes the sound iterator. - */ - virtual void init() {} - - /** - * Reads the next MIDI operation _or_ delta time. - * @param buf The buffer to write to (needs to be able to store at least 4 bytes) - * @param result Number of bytes written to the buffer - * (equals the number of bytes that need to be passed - * to the lower layers) for 0, the cue value for SI_CUE, - * or the number of loops remaining for SI_LOOP. - * @return zero if a MIDI operation was written, SI_FINISHED - * if the song has finished playing, SI_LOOP if looping - * (after updating the loop variable), SI_CUE if we found - * a cue, SI_PCM if a PCM was found, or the number of ticks - * to wait before this function should be called next. - * - * @note If SI_PCM is returned, get_pcm() may be used to retrieve the associated - * PCM, but this must be done before any subsequent calls to next(). - * - * @todo The actual buffer size should either be specified or passed in, so that - * we can detect buffer overruns. - */ - virtual int nextCommand(byte *buf, int *result) = 0; - - /** - Checks for the presence of a pcm sample. - * @return NULL if no PCM data was found, an AudioStream otherwise. - */ - virtual Audio::AudioStream *getAudioStream() = 0; - - /** - * Handles a message to the song iterator. - * @param msg the message to handle - * @return NULL if the message was not understood, - * this if the message could be handled, or a new song iterator - * if the current iterator had to be morphed (but the message could - * still be handled) - * - * @note This function is not supposed to be called directly; use - * songit_handle_message() instead. It should not recurse, since songit_handle_message() - * takes care of that and makes sure that its delegate received the message (and - * was morphed) before self. - */ - virtual SongIterator *handleMessage(Message msg) = 0; - - /** - * Gets the song position to store in a savegame. - */ - virtual int getTimepos() = 0; - - /** - * Clone this song iterator. - * @param delta number of ticks that still need to elapse until the - * next item should be read from the song iterator - */ - virtual SongIterator *clone(int delta) = 0; - - -private: - // Make the assignment operator unreachable, just in case... - SongIterator& operator=(const SongIterator&); -}; - - -/********************************/ -/*-- Song iterator operations --*/ -/********************************/ - -enum SongIteratorType { - SCI_SONG_ITERATOR_TYPE_SCI0 = 0, - SCI_SONG_ITERATOR_TYPE_SCI1 = 1 -}; - -#define IT_READER_MASK_MIDI (1 << 0) -#define IT_READER_MASK_DELAY (1 << 1) -#define IT_READER_MASK_LOOP (1 << 2) -#define IT_READER_MASK_CUE (1 << 3) -#define IT_READER_MASK_PCM (1 << 4) -#define IT_READER_MAY_FREE (1 << 10) /* Free SI_FINISHED iterators */ -#define IT_READER_MAY_CLEAN (1 << 11) -/* MAY_CLEAN: May instantiate cleanup iterators -** (use for players; this closes open channels at the end of a song) */ - -#define IT_READER_MASK_ALL ( IT_READER_MASK_MIDI \ - | IT_READER_MASK_DELAY \ - | IT_READER_MASK_LOOP \ - | IT_READER_MASK_CUE \ - | IT_READER_MASK_PCM ) - -/* Convenience wrapper around it->next -** Parameters: (SongIterator **it) Reference to the iterator to access -** (byte *) buf: The buffer to write to (needs to be able to -** store at least 4 bytes) -** (int) mask: IT_READER_MASK options specifying the events to -** listen for -** Returns : (int) zero if a MIDI operation was written, SI_FINISHED -** if the song has finished playing, SI_LOOP if looping -** (after updating the loop variable), SI_CUE if we found -** a cue, SI_PCM if a PCM was found, or the number of ticks -** to wait before this function should be called next. -** (int) *result: Number of bytes written to the buffer -** (equals the number of bytes that need to be passed -** to the lower layers) for 0, the cue value for SI_CUE, -** or the number of loops remaining for SI_LOOP. -*/ -int songit_next(SongIterator **it, byte *buf, int *result, int mask); - -/* Constructs a new song iterator object -** Parameters: (byte *) data: The song data to iterate over -** (uint) size: Number of bytes in the song -** (int) type: One of the SCI_SONG_ITERATOR_TYPEs -** (songit_id_t) id: An ID for addressing the song iterator -** Returns : (SongIterator *) A newly allocated but uninitialized song -** iterator, or NULL if 'type' was invalid or unsupported -*/ -SongIterator *songit_new(byte *data, uint size, SongIteratorType type, songit_id_t id); - -/* Constructs a new song timer iterator object -** Parameters: (int) delta: The delta after which to fire SI_FINISHED -** Returns : (SongIterator *) A newly allocated but uninitialized song -** iterator -*/ -SongIterator *new_timer_iterator(int delta); - -/* Handles a message to the song iterator -** Parameters: (SongIterator **): A reference to the variable storing the song iterator -** Returns : (int) Non-zero if the message was understood -** The song iterator may polymorph as result of msg, so a writeable reference is required. -*/ -int songit_handle_message(SongIterator **it_reg, SongIterator::Message msg); - - -/* Creates a new song iterator which fast-forwards -** Parameters: (SongIterator *) it: The iterator to wrap -** (int) delta: The number of ticks to skip -** Returns : (SongIterator) A newly created song iterator -** which skips all delta times -** until 'delta' has been used up -*/ -SongIterator *new_fast_forward_iterator(SongIterator *it, int delta); - -/* Combines two song iterators into one -** Parameters: (sfx_iterator_t *) it1: One of the two iterators, or NULL -** (sfx_iterator_t *) it2: The other iterator, or NULL -** Returns : (sfx_iterator_t *) A combined iterator -** If a combined iterator is returned, it will be flagged to be allowed to -** dispose of 'it1' and 'it2', where applicable. This means that this -** call should be used by song players, but not by the core sound system -*/ -SongIterator *sfx_iterator_combine(SongIterator *it1, SongIterator *it2); - -} // End of namespace Sci - -#endif // USE_OLD_MUSIC_FUNCTIONS - -#endif // SCI_SFX_SFX_ITERATOR_H diff --git a/engines/sci/sound/iterator/iterator_internal.h b/engines/sci/sound/iterator/iterator_internal.h deleted file mode 100644 index 5a0f0d3ec9..0000000000 --- a/engines/sci/sound/iterator/iterator_internal.h +++ /dev/null @@ -1,276 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#ifndef SCI_SFX_SFX_ITERATOR_INTERNAL -#define SCI_SFX_SFX_ITERATOR_INTERNAL - -#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS - -#ifdef USE_OLD_MUSIC_FUNCTIONS -#include "sci/sound/iterator/iterator.h" -#include "sci/sound/drivers/mididriver.h" - -#include "common/array.h" -#include "common/list.h" - -namespace Sci { - -/* Iterator types */ - -enum { - SI_STATE_UNINITIALISED = -1, - SI_STATE_DELTA_TIME = 0, ///< Now at a delta time - SI_STATE_COMMAND = 1, ///< Now at a MIDI operation - SI_STATE_PENDING = 2, ///< Pending for loop - SI_STATE_FINISHED = 3, ///< End of song - SI_STATE_PCM = 4, ///< Should report a PCM next (-> DELTA_TIME) - SI_STATE_PCM_MAGIC_DELTA = 5 ///< Should report a ``magic'' one tick delta time next (goes on to FINISHED) -}; - -struct SongIteratorChannel { - - int state; ///< State of this song iterator channel - int offset; ///< Offset into the data chunk */ - int end; ///< Last allowed byte in track */ - int id; ///< Some channel ID */ - - /** - * Number of ticks before the specified channel is next used, or - * CHANNEL_DELAY_MISSING to indicate that the delay has not yet - * been read. - */ - int delay; - - /* Two additional offsets for recovering: */ - int loop_offset; - int initial_offset; - - int playmask; ///< Active playmask (MIDI channels to play in here) */ - int loop_timepos; ///< Total delay for this channel's loop marker */ - int total_timepos; ///< Number of ticks since the beginning, ignoring loops */ - int timepos_increment; ///< Number of ticks until the next command (to add) */ - - byte last_cmd; ///< Last operation executed, for running status */ - -public: - void init(int id, int offset, int end); - void resetSynthChannels(); -}; - -class BaseSongIterator : public SongIterator { -public: - int _polyphony[MIDI_CHANNELS]; ///< # of simultaneous notes on each - - int _ccc; ///< Cumulative cue counter, for those who need it - byte _resetflag; ///< for 0x4C -- on DoSound StopSound, do we return to start? - int _deviceId; ///< ID of the device we generating events for - int _numActiveChannels; ///< Number of active channels - Common::Array<byte> _data; ///< Song data - - int _loops; ///< Number of loops remaining - -public: - BaseSongIterator(byte *data, uint size, songit_id_t id); - -protected: - int parseMidiCommand(byte *buf, int *result, SongIteratorChannel *channel, int flags); - int processMidi(byte *buf, int *result, SongIteratorChannel *channel, int flags); -}; - -/********************************/ -/*--------- SCI 0 --------------*/ -/********************************/ - -class Sci0SongIterator : public BaseSongIterator { -public: - SongIteratorChannel _channel; - -public: - Sci0SongIterator(byte *data, uint size, songit_id_t id); - - int nextCommand(byte *buf, int *result); - Audio::AudioStream *getAudioStream(); - SongIterator *handleMessage(Message msg); - void init(); - int getTimepos(); - SongIterator *clone(int delta); -}; - - -/********************************/ -/*--------- SCI 1 --------------*/ -/********************************/ - - -struct Sci1Sample { - /** - * Time left-- initially, this is 'Sample point 1'. - * After initialisation, it is 'sample point 1 minus the sample - * point of the previous sample' - */ - int delta; - int size; - bool announced; /* Announced for download (SI_PCM) */ - int rate; - byte *_data; -}; - -class Sci1SongIterator : public BaseSongIterator { -public: - SongIteratorChannel _channels[MIDI_CHANNELS]; - - /* Invariant: Whenever channels[i].delay == CHANNEL_DELAY_MISSING, - ** channel_offset[i] points to a delta time object. */ - - bool _initialised; /**!< Whether the MIDI channel setup has been initialised */ - int _numChannels; /**!< Number of channels actually used */ - Common::List<Sci1Sample> _samples; - int _numLoopedChannels; /**!< Number of channels that are ready to loop */ - - int _delayRemaining; /**!< Number of ticks that haven't been polled yet */ - int _hold; - -public: - Sci1SongIterator(byte *data, uint size, songit_id_t id); - ~Sci1SongIterator(); - - int nextCommand(byte *buf, int *result); - Audio::AudioStream *getAudioStream(); - SongIterator *handleMessage(Message msg); - void init(); - int getTimepos(); - SongIterator *clone(int delta); - -private: - int initSample(const int offset); - int initSong(); - - int getSmallestDelta() const; - - void updateDelta(int delta); - - /** Checks that none of the channels is waiting for its delta to be read */ - bool noDeltaTime() const; - - /** Determine the channel # of the next active event, or -1 */ - int getCommandIndex() const; -}; - -#define PLAYMASK_NONE 0x0 - -/***************************/ -/*--------- Timer ---------*/ -/***************************/ - -/** - * A song iterator which waits a specified time and then fires - * SI_FINISHED. Used by DoSound, where audio resources are played (SCI1) - */ -class TimerSongIterator : public SongIterator { -protected: - int _delta; /**!< Remaining time */ - -public: - TimerSongIterator(int delta) : _delta(delta) {} - - int nextCommand(byte *buf, int *result); - Audio::AudioStream *getAudioStream() { return NULL; } - SongIterator *handleMessage(Message msg) { return NULL; } - int getTimepos() { return 0; } - SongIterator *clone(int delta) { return new TimerSongIterator(*this); } -}; - -/**********************************/ -/*--------- Fast Forward ---------*/ -/**********************************/ - -/** - * A song iterator which fast-forwards another iterator. - * Skips all delta times until a specified 'delta' has been used up. - */ -class FastForwardSongIterator : public SongIterator { -protected: - SongIterator *_delegate; - int _delta; /**!< Remaining time */ - -public: - FastForwardSongIterator(SongIterator *capsit, int delta); - - int nextCommand(byte *buf, int *result); - Audio::AudioStream *getAudioStream(); - SongIterator *handleMessage(Message msg); - int getTimepos(); - SongIterator *clone(int delta); -}; - - -/**********************************/ -/*--------- Tee iterator ---------*/ -/**********************************/ - -enum { - TEE_LEFT = 0, - TEE_RIGHT = 1, - TEE_LEFT_ACTIVE = (1<<0), - TEE_RIGHT_ACTIVE = (1<<1), - TEE_LEFT_READY = (1<<2), /**!< left result is ready */ - TEE_RIGHT_READY = (1<<3), /**!< right result is ready */ - TEE_LEFT_PCM = (1<<4), - TEE_RIGHT_PCM = (1<<5) -}; - -/** - * This iterator combines two iterators, returns the next event available from either. - */ -class TeeSongIterator : public SongIterator { -public: - int _status; - - bool _readyToMorph; /**!< One of TEE_MORPH_* above */ - - struct { - SongIterator *it; - byte buf[4]; - int result; - int retval; - } _children[2]; - -public: - TeeSongIterator(SongIterator *left, SongIterator *right); - ~TeeSongIterator(); - - int nextCommand(byte *buf, int *result); - Audio::AudioStream *getAudioStream(); - SongIterator *handleMessage(Message msg); - void init(); - int getTimepos() { return 0; } - SongIterator *clone(int delta); -}; - -} // End of namespace Sci - -#endif // USE_OLD_MUSIC_FUNCTIONS - -#endif // SCI_SFX_SFX_ITERATOR_INTERNAL diff --git a/engines/sci/sound/iterator/songlib.cpp b/engines/sci/sound/iterator/songlib.cpp deleted file mode 100644 index 8bc2e8f476..0000000000 --- a/engines/sci/sound/iterator/songlib.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS - -#ifdef USE_OLD_MUSIC_FUNCTIONS -#include "sci/sound/iterator/core.h" -#include "sci/sound/iterator/iterator.h" - -namespace Sci { - -#define debug_stream stderr - -Song::Song() : _wakeupTime(0, SFX_TICKS_PER_SEC) { - _handle = 0; - _resourceNum = 0; - _priority = 0; - _status = SOUND_STATUS_STOPPED; - - _restoreBehavior = RESTORE_BEHAVIOR_CONTINUE; - _restoreTime = 0; - - _loops = 0; - _hold = 0; - - _it = 0; - _delay = 0; - - _next = NULL; - _nextPlaying = NULL; - _nextStopping = NULL; -} - -Song::Song(SongHandle handle, SongIterator *it, int priority) : _wakeupTime(0, SFX_TICKS_PER_SEC) { - _handle = handle; - _resourceNum = 0; - _priority = priority; - _status = SOUND_STATUS_STOPPED; - - _restoreBehavior = RESTORE_BEHAVIOR_CONTINUE; - _restoreTime = 0; - - _loops = 0; - _hold = 0; - - _it = it; - _delay = 0; - - _next = NULL; - _nextPlaying = NULL; - _nextStopping = NULL; -} - -void SongLibrary::addSong(Song *song) { - Song **seeker = NULL; - int pri = song->_priority; - - if (NULL == song) { - warning("addSong(): NULL passed for song"); - return; - } - - seeker = &_lib; - while (*seeker && ((*seeker)->_priority > pri)) - seeker = &((*seeker)->_next); - - song->_next = *seeker; - *seeker = song; -} - -void SongLibrary::freeSounds() { - Song *next = _lib; - while (next) { - Song *song = next; - delete song->_it; - song->_it = NULL; - next = song->_next; - delete song; - } - _lib = NULL; -} - - -Song *SongLibrary::findSong(SongHandle handle) { - Song *seeker = _lib; - - while (seeker) { - if (seeker->_handle == handle) - break; - seeker = seeker->_next; - } - - return seeker; -} - -Song *SongLibrary::findNextActive(Song *other) { - Song *seeker = other ? other->_next : _lib; - - while (seeker) { - if ((seeker->_status == SOUND_STATUS_WAITING) || - (seeker->_status == SOUND_STATUS_PLAYING)) - break; - seeker = seeker->_next; - } - - /* Only return songs that have equal priority */ - if (other && seeker && other->_priority > seeker->_priority) - return NULL; - - return seeker; -} - -Song *SongLibrary::findFirstActive() { - return findNextActive(NULL); -} - -int SongLibrary::removeSong(SongHandle handle) { - int retval; - Song *goner = _lib; - - if (!goner) - return -1; - - if (goner->_handle == handle) - _lib = goner->_next; - - else { - while ((goner->_next) && (goner->_next->_handle != handle)) - goner = goner->_next; - - if (goner->_next) { /* Found him? */ - Song *oldnext = goner->_next; - - goner->_next = goner->_next->_next; - goner = oldnext; - } else return -1; /* No. */ - } - - retval = goner->_status; - - delete goner->_it; - delete goner; - - return retval; -} - -int SongLibrary::countSongs() { - Song *seeker = _lib; - int retval = 0; - - while (seeker) { - retval++; - seeker = seeker->_next; - } - - return retval; -} - -void SongLibrary::setSongRestoreBehavior(SongHandle handle, RESTORE_BEHAVIOR action) { - Song *seeker = findSong(handle); - - seeker->_restoreBehavior = action; -} - -} // End of namespace Sci - -#endif // USE_OLD_MUSIC_FUNCTIONS diff --git a/engines/sci/sound/iterator/songlib.h b/engines/sci/sound/iterator/songlib.h deleted file mode 100644 index acb704edaa..0000000000 --- a/engines/sci/sound/iterator/songlib.h +++ /dev/null @@ -1,171 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* Song library */ - -#ifndef SCI_SFX_SFX_SONGLIB_H -#define SCI_SFX_SFX_SONGLIB_H - -#include "common/scummsys.h" -#include "sound/timestamp.h" - -#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS -#ifdef USE_OLD_MUSIC_FUNCTIONS - -namespace Sci { - -class SongIterator; - -#define SOUND_STATUS_STOPPED 0 -#define SOUND_STATUS_PLAYING 1 -#define SOUND_STATUS_SUSPENDED 2 -/* suspended: only if ordered from kernel space */ -#define SOUND_STATUS_WAITING 3 -/* "waiting" means "tagged for playing, but not active right now" */ - -typedef unsigned long SongHandle; - -enum RESTORE_BEHAVIOR { - RESTORE_BEHAVIOR_CONTINUE, /* restart a song when restored from - a saved game */ - RESTORE_BEHAVIOR_RESTART /* continue it from where it was */ -}; - -class Song { -public: - SongHandle _handle; - int _resourceNum; /**<! Resource number */ - int _priority; /**!< Song priority (more important if priority is higher) */ - int _status; /* See above */ - - int _restoreBehavior; - int _restoreTime; - - /* Grabbed from the sound iterator, for save/restore purposes */ - int _loops; - int _hold; - - SongIterator *_it; - int _delay; /**!< Delay before accessing the iterator, in ticks */ - - Audio::Timestamp _wakeupTime; /**!< Timestamp indicating the next MIDI event */ - - Song *_next; /**!< Next song or NULL if this is the last one */ - - /** - * Next playing song. Used by the core song system. - */ - Song *_nextPlaying; - - /** - * Next song pending stopping. Used exclusively by the core song system's - * _update_multi_song() - */ - Song *_nextStopping; - -public: - - Song(); - - /** - * Initializes a new song. - * @param handle the sound handle - * @param it the song - * @param priority the song's priority - * @return a freshly allocated song - */ - Song(SongHandle handle, SongIterator *it, int priority); -}; - - -class SongLibrary { -public: - Song *_lib; - -public: - SongLibrary() : _lib(0) {} - - /** Frees a song library. */ - void freeSounds(); - - /** - * Adds a song to a song library. - * @param song song to add - */ - void addSong(Song *song); - - /** - * Looks up the song with the specified handle. - * @param handle sound handle to look for - * @return the song or NULL if it wasn't found - */ - Song *findSong(SongHandle handle); - - /** - * Finds the first song playing with the highest priority. - * @return the song that should be played next, or NULL if there is none - */ - Song *findFirstActive(); - - /** - * Finds the next song playing with the highest priority. - * - * The functions 'findFirstActive' and 'findNextActive' - * allow to iterate over all songs that satisfy the requirement of - * being 'playable'. - * - * @param song a song previously returned from the song library - * @return the next song to play relative to 'song', or NULL if none are left - */ - Song *findNextActive(Song *song); - - /** - * Removes a song from the library. - * @param handle handle of the song to remove - * @return the status of the song that was removed - */ - int removeSong(SongHandle handle); - - /** - * Counts the number of songs in a song library. - * @return the number of songs - */ - int countSongs(); - - /** - * Determines what should be done with the song "handle" when restoring - * it from a saved game. - * @param handle sound handle being restored - * @param action desired action - */ - void setSongRestoreBehavior(SongHandle handle, - RESTORE_BEHAVIOR action); -}; - -} // End of namespace Sci - -#endif // USE_OLD_MUSIC_FUNCTIONS - -#endif // SCI_SSFX_SFX_SONGLIB_H diff --git a/engines/sci/sound/iterator/test-iterator.cpp b/engines/sci/sound/iterator/test-iterator.cpp deleted file mode 100644 index 0d603a89fd..0000000000 --- a/engines/sci/sound/iterator/test-iterator.cpp +++ /dev/null @@ -1,423 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "iterator.h" -#include "iterator_internal.h" -#include <stdarg.h> -#include <stdio.h> - -using namespace Sci; - -#define ASSERT_S(x) if (!(x)) { error("Failed assertion in L%d: " #x, __LINE__); return; } -#define ASSERT(x) ASSERT_S(x) - -/* Tests the song iterators */ - -int errors = 0; - -void error(char *fmt, ...) { - va_list ap; - - fprintf(stderr, "[ERROR] "); - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - ++errors; -} - - -/* The simple iterator will finish after a fixed amount of time. Before that, -** it emits (absolute) cues in ascending order. */ -struct simple_iterator : public SongIterator { - int lifetime_remaining; - char *cues; - int cue_counter; - int cue_progress; - int cues_nr; -}; - -int simple_it_next(SongIterator *_self, unsigned char *buf, int *result) { - simple_iterator *self = (simple_iterator *)_self; - - if (self->lifetime_remaining == -1) { - error("Song iterator called post mortem"); - return SI_FINISHED; - } - - if (self->lifetime_remaining) { - - if (self->cue_counter < self->cues_nr) { - int time_to_cue = self->cues[self->cue_counter]; - - if (self->cue_progress == time_to_cue) { - ++self->cue_counter; - self->cue_progress = 0; - *result = self->cue_counter; - return SI_ABSOLUTE_CUE; - } else { - int retval = time_to_cue - self->cue_progress; - self->cue_progress = time_to_cue; - - if (retval > self->lifetime_remaining) { - retval = self->lifetime_remaining; - self->lifetime_remaining = 0; - self->cue_progress = retval; - return retval; - } - - self->lifetime_remaining -= retval; - return retval; - } - } else { - int retval = self->lifetime_remaining; - self->lifetime_remaining = 0; - return retval; - } - - } else { - self->lifetime_remaining = -1; - return SI_FINISHED; - } -} - -Audio::AudioStream *simple_it_pcm_feed(SongIterator *_self) { - error("No PCM feed"); - return NULL; -} - -void simple_it_init(SongIterator *_self) { -} - -SongIterator *simple_it_handle_message(SongIterator *_self, SongIterator::Message msg) { - return NULL; -} - -void simple_it_cleanup(SongIterator *_self) { -} - -/* Initialises the simple iterator. -** Parameters: (int) delay: Number of ticks until the iterator finishes -** (int *) cues: An array of cue delays (cue values are [1,2...]) -** (int) cues_nr: Number of cues in ``cues'' -** The first cue is emitted after cues[0] ticks, and it is 1. After cues[1] additional ticks -** the next cue is emitted, and so on. */ -SongIterator *setup_simple_iterator(int delay, char *cues, int cues_nr) { - simple_iterator.lifetime_remaining = delay; - simple_iterator.cues = cues; - simple_iterator.cue_counter = 0; - simple_iterator.cues_nr = cues_nr; - simple_iterator.cue_progress = 0; - - simple_iterator.ID = 42; - simple_iterator.channel_mask = 0x004f; - simple_iterator.flags = 0; - simple_iterator.priority = 1; - - simple_iterator.death_listeners_nr = 0; - - simple_iterator.cleanup = simple_it_cleanup; - simple_iterator.init = simple_it_init; - simple_iterator.handle_message = simple_it_handle_message; - simple_iterator.get_pcm_feed = simple_it_pcm_feed; - simple_iterator.next = simple_it_next; - - return (SongIterator *) &simple_iterator; -} - -#define ASSERT_SIT ASSERT(it == simple_it) -#define ASSERT_FFIT ASSERT(it == ff_it) -#define ASSERT_NEXT(n) ASSERT(songit_next(&it, data, &result, IT_READER_MASK_ALL) == n) -#define ASSERT_RESULT(n) ASSERT(result == n) -#define ASSERT_CUE(n) ASSERT_NEXT(SI_ABSOLUTE_CUE); ASSERT_RESULT(n) - -void test_simple_it() { - SongIterator *it; - SongIterator *simple_it = (SongIterator *) & simple_iterator; - unsigned char data[4]; - int result; - puts("[TEST] simple iterator (test artifact)"); - - it = setup_simple_iterator(42, NULL, 0); - - ASSERT_SIT; - ASSERT_NEXT(42); - ASSERT_SIT; - ASSERT_NEXT(SI_FINISHED); - ASSERT_SIT; - - it = setup_simple_iterator(42, "\003\004", 2); - ASSERT_SIT; - ASSERT_NEXT(3); - ASSERT_CUE(1); - ASSERT_SIT; - ASSERT_NEXT(4); - ASSERT_CUE(2); - ASSERT_SIT; -// warning("XXX => %d", songit_next(&it, data, &result, IT_READER_MASK_ALL)); - ASSERT_NEXT(35); - ASSERT_NEXT(SI_FINISHED); - ASSERT_SIT; - - puts("[TEST] Test OK."); -} - -void test_fastforward() { - SongIterator *it; - SongIterator *simple_it = (SongIterator *) & simple_iterator; - SongIterator *ff_it; - unsigned char data[4]; - int result; - puts("[TEST] fast-forward iterator"); - - it = setup_simple_iterator(42, NULL, 0); - ff_it = it = new_fast_forward_iterator(it, 0); - ASSERT_FFIT; - ASSERT_NEXT(42); - ASSERT_SIT; /* Must have morphed back */ - ASSERT_NEXT(SI_FINISHED); - ASSERT_SIT; - - it = setup_simple_iterator(42, NULL, 0); - ff_it = it = new_fast_forward_iterator(it, 1); - ASSERT_FFIT; - ASSERT_NEXT(41); - /* May or may not have morphed back here */ - ASSERT_NEXT(SI_FINISHED); - ASSERT_SIT; - - it = setup_simple_iterator(42, NULL, 0); - ff_it = it = new_fast_forward_iterator(it, 41); - ASSERT_FFIT; - ASSERT_NEXT(1); - /* May or may not have morphed back here */ - ASSERT_NEXT(SI_FINISHED); - ASSERT_SIT; - - it = setup_simple_iterator(42, NULL, 0); - ff_it = it = new_fast_forward_iterator(it, 42); - ASSERT_NEXT(SI_FINISHED); - /* May or may not have morphed back here */ - - it = setup_simple_iterator(42, NULL, 0); - ff_it = it = new_fast_forward_iterator(it, 10000); - ASSERT_NEXT(SI_FINISHED); - /* May or may not have morphed back here */ - - it = setup_simple_iterator(42, "\003\004", 2); - ff_it = it = new_fast_forward_iterator(it, 2); - ASSERT_FFIT; - ASSERT_NEXT(1); - ASSERT_CUE(1); - ASSERT_SIT; - ASSERT_NEXT(4); - ASSERT_CUE(2); - ASSERT_SIT; - ASSERT_NEXT(35); - ASSERT_NEXT(SI_FINISHED); - ASSERT_SIT; - - it = setup_simple_iterator(42, "\003\004", 2); - ff_it = it = new_fast_forward_iterator(it, 5); - ASSERT_FFIT; - ASSERT_CUE(1); - ASSERT_FFIT; - ASSERT_NEXT(2); - ASSERT_CUE(2); - ASSERT_SIT; - ASSERT_NEXT(35); - ASSERT_NEXT(SI_FINISHED); - ASSERT_SIT; - - it = setup_simple_iterator(42, "\003\004", 2); - ff_it = it = new_fast_forward_iterator(it, 41); - ASSERT_FFIT; - ASSERT_CUE(1); - ASSERT_FFIT; - ASSERT_CUE(2); - ASSERT_FFIT; - ASSERT_NEXT(1); - ASSERT_NEXT(SI_FINISHED); - ASSERT_SIT; - - puts("[TEST] Test OK."); -} - -#define SIMPLE_SONG_SIZE 50 - -static unsigned char simple_song[SIMPLE_SONG_SIZE] = { - 0x00, /* Regular song */ - /* Only use channel 0 for all devices */ - 0x02, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* Song begins here */ - 42, 0x90, 60, 0x7f, /* Play C after 42 ticks */ - 02, 64, 0x42, /* Play E after 2 more ticks, using running status mode */ - 0xf8, 10, 0x80, 60, 0x02, /* Stop C after 250 ticks */ - 0, 64, 0x00, /* Stop E immediately */ - 00, 0xfc /* Stop song */ -}; - -#define ASSERT_MIDI3(cmd, arg0, arg1) \ - ASSERT(data[0] == cmd); \ - ASSERT(data[1] == arg0); \ - ASSERT(data[2] == arg1); - -void test_iterator_sci0() { - SongIterator *it = songit_new(simple_song, SIMPLE_SONG_SIZE, SCI_SONG_ITERATOR_TYPE_SCI0, 0l); - unsigned char data[4]; - int result; - SIMSG_SEND(it, SIMSG_SET_PLAYMASK(0x0001)); /* Initialise song, enabling channel 0 */ - - puts("[TEST] SCI0-style song"); - ASSERT_NEXT(42); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 60, 0x7f); - ASSERT_NEXT(2); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 64, 0x42); - ASSERT_NEXT(250); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 60, 0x02); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 64, 0x00); - ASSERT_NEXT(SI_FINISHED); - puts("[TEST] Test OK."); -} - - - -void test_iterator_sci0_loop() { - SongIterator *it = songit_new(simple_song, SIMPLE_SONG_SIZE, SCI_SONG_ITERATOR_TYPE_SCI0, 0l); - unsigned char data[4]; - int result; - SIMSG_SEND(it, SIMSG_SET_PLAYMASK(0x0001)); /* Initialise song, enabling channel 0 */ - SIMSG_SEND(it, SIMSG_SET_LOOPS(2)); /* Loop one additional time */ - - puts("[TEST] SCI0-style song with looping"); - ASSERT_NEXT(42); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 60, 0x7f); - ASSERT_NEXT(2); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 64, 0x42); - ASSERT_NEXT(250); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 60, 0x02); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 64, 0x00); - ASSERT_NEXT(SI_LOOP); - ASSERT_NEXT(42); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 60, 0x7f); - ASSERT_NEXT(2); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 64, 0x42); - ASSERT_NEXT(250); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 60, 0x02); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 64, 0x00); - ASSERT_NEXT(SI_FINISHED); - puts("[TEST] Test OK."); -} - - - -#define LOOP_SONG_SIZE 54 - -unsigned char loop_song[LOOP_SONG_SIZE] = { - 0x00, /* Regular song song */ - /* Only use channel 0 for all devices */ - 0x02, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* Song begins here */ - 42, 0x90, 60, 0x7f, /* Play C after 42 ticks */ - 13, 0x80, 60, 0x00, /* Stop C after 13 ticks */ - 00, 0xCF, 0x7f, /* Set loop point */ - 02, 0x90, 64, 0x42, /* Play E after 2 more ticks, using running status mode */ - 03, 0x80, 64, 0x00, /* Stop E after 3 ticks */ - 00, 0xfc /* Stop song/loop */ -}; - - -void test_iterator_sci0_mark_loop() { - SongIterator *it = songit_new(loop_song, LOOP_SONG_SIZE, SCI_SONG_ITERATOR_TYPE_SCI0, 0l); - unsigned char data[4]; - int result; - SIMSG_SEND(it, SIMSG_SET_PLAYMASK(0x0001)); /* Initialise song, enabling channel 0 */ - SIMSG_SEND(it, SIMSG_SET_LOOPS(3)); /* Loop once more */ - - puts("[TEST] SCI0-style song with loop mark, looping"); - ASSERT_NEXT(42); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 60, 0x7f); - ASSERT_NEXT(13); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 60, 0x00); - /* Loop point here: we don't observe that in the iterator interface yet, though */ - ASSERT_NEXT(2); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 64, 0x42); - ASSERT_NEXT(3); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 64, 0x00); - /* Now we loop back to the loop pont */ - ASSERT_NEXT(SI_LOOP); - ASSERT_NEXT(2); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 64, 0x42); - ASSERT_NEXT(3); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 64, 0x00); - /* ...and one final time */ - ASSERT_NEXT(SI_LOOP); - ASSERT_NEXT(2); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 64, 0x42); - ASSERT_NEXT(3); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 64, 0x00); - - ASSERT_NEXT(SI_FINISHED); - puts("[TEST] Test OK."); -} - - - -int main(int argc, char **argv) { - test_simple_it(); - test_fastforward(); - test_iterator_sci0(); - test_iterator_sci0_loop(); - test_iterator_sci0_mark_loop(); - if (errors != 0) - warning("[ERROR] %d errors total", errors); - return (errors != 0); -} diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 3ee8a3a83d..cc09ba79f0 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -43,30 +43,39 @@ enum SciMidiCommands { // MidiParser_SCI // -MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion) : +MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion, SciMusic *music) : MidiParser() { _soundVersion = soundVersion; + _music = music; _mixedData = NULL; // mididata contains delta in 1/60th second // values of ppqn and tempo are found experimentally and may be wrong _ppqn = 1; setTempo(16667); - _volume = 0; + _volume = 127; _signalSet = false; _signalToSet = 0; _dataincAdd = false; _dataincToAdd = 0; _resetOnPause = false; - _channelsUsed = 0; - - for (int i = 0; i < 16; i++) - _channelRemap[i] = i; + _pSnd = 0; } MidiParser_SCI::~MidiParser_SCI() { unloadMusic(); + // we do this, so that MidiParser won't be able to call his own ::allNotesOff() + // this one would affect all channels and we can't let that happen + _driver = 0; +} + +void MidiParser_SCI::mainThreadBegin() { + _mainThreadCalled = true; +} + +void MidiParser_SCI::mainThreadEnd() { + _mainThreadCalled = false; } bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, int channelFilterMask, SciVersion soundVersion) { @@ -75,7 +84,14 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in _pSnd = psnd; _soundVersion = soundVersion; - setVolume(psnd->volume); + for (int i = 0; i < 16; i++) { + _channelUsed[i] = false; + _channelRemap[i] = -1; + _channelMuted[i] = false; + _channelVolume[i] = 127; + } + _channelRemap[9] = 9; // never map channel 9, because that's used for percussion + _channelRemap[15] = 15; // never map channel 15, because thats used by sierra internally if (channelFilterMask) { // SCI0 only has 1 data stream, but we need to filter out channels depending on music hardware selection @@ -86,30 +102,272 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in _num_tracks = 1; _tracks[0] = _mixedData; - setTrack(0); + if (_pSnd) + setTrack(0); _loopTick = 0; - if (_soundVersion <= SCI_VERSION_0_LATE) { - // Set initial voice count - for (int i = 0; i < 16; ++i) { - byte voiceCount = 0; - if (channelFilterMask & (1 << i)) - voiceCount = psnd->soundRes->getInitialVoiceCount(i); - _driver->send(0xB0 | i, 0x4B, voiceCount); + return true; +} + +byte MidiParser_SCI::midiGetNextChannel(long ticker) { + byte curr = 0xFF; + long closest = ticker + 1000000, next = 0; + + for (int i = 0; i < _track->channelCount; i++) { + if (_track->channels[i].time == -1) // channel ended + continue; + SoundResource::Channel *curChannel = &_track->channels[i]; + if (curChannel->curPos >= curChannel->size) + continue; + next = curChannel->data[curChannel->curPos]; // when the next event should occur + if (next == 0xF8) // 0xF8 means 240 ticks delay + next = 240; + next += _track->channels[i].time; + if (next < closest) { + curr = i; + closest = next; + } + } + + return curr; +} + +byte *MidiParser_SCI::midiMixChannels() { + int totalSize = 0; + + for (int i = 0; i < _track->channelCount; i++) { + _track->channels[i].time = 0; + _track->channels[i].prev = 0; + _track->channels[i].curPos = 0; + totalSize += _track->channels[i].size; + } + + byte *outData = new byte[totalSize * 2]; // FIXME: creates overhead and still may be not enough to hold all data + _mixedData = outData; + long ticker = 0; + byte channelNr, curDelta; + byte midiCommand = 0, midiParam, global_prev = 0; + long newDelta; + SoundResource::Channel *channel; + + while ((channelNr = midiGetNextChannel(ticker)) != 0xFF) { // there is still an active channel + channel = &_track->channels[channelNr]; + curDelta = channel->data[channel->curPos++]; + channel->time += (curDelta == 0xF8 ? 240 : curDelta); // when the command is supposed to occur + if (curDelta == 0xF8) + continue; + newDelta = channel->time - ticker; + ticker += newDelta; + + midiCommand = channel->data[channel->curPos++]; + if (midiCommand != kEndOfTrack) { + // Write delta + while (newDelta > 240) { + *outData++ = 0xF8; + newDelta -= 240; + } + *outData++ = (byte)newDelta; + } + // Write command + switch (midiCommand) { + case 0xF0: // sysEx + *outData++ = midiCommand; + do { + midiParam = channel->data[channel->curPos++]; + *outData++ = midiParam; + } while (midiParam != 0xF7); + break; + case kEndOfTrack: // end of channel + channel->time = -1; + break; + default: // MIDI command + if (midiCommand & 0x80) { + midiParam = channel->data[channel->curPos++]; + } else {// running status + midiParam = midiCommand; + midiCommand = channel->prev; + } + + // remember which channel got used for channel remapping + byte midiChannel = midiCommand & 0xF; + _channelUsed[midiChannel] = true; + + if (midiCommand != global_prev) + *outData++ = midiCommand; + *outData++ = midiParam; + if (nMidiParams[(midiCommand >> 4) - 8] == 2) + *outData++ = channel->data[channel->curPos++]; + channel->prev = midiCommand; + global_prev = midiCommand; + } + } + + // Insert stop event + *outData++ = 0; // Delta + *outData++ = 0xFF; // Meta event + *outData++ = 0x2F; // End of track (EOT) + *outData++ = 0x00; + *outData++ = 0x00; + return _mixedData; +} + +// This is used for SCI0 sound-data. SCI0 only has one stream that may +// contain several channels and according to output device we remove +// certain channels from that data. +byte *MidiParser_SCI::midiFilterChannels(int channelMask) { + SoundResource::Channel *channel = &_track->channels[0]; + byte *channelData = channel->data; + byte *channelDataEnd = channel->data + channel->size; + byte *outData = new byte[channel->size + 5]; + byte curChannel = 15, curByte, curDelta; + byte command = 0, lastCommand = 0; + int delta = 0; + int midiParamCount = 0; + + _mixedData = outData; + + while (channelData < channelDataEnd) { + curDelta = *channelData++; + if (curDelta == 0xF8) { + delta += 240; + continue; + } + delta += curDelta; + curByte = *channelData++; + + switch (curByte) { + case 0xF0: // sysEx + case kEndOfTrack: // end of channel + command = curByte; + curChannel = 15; + break; + default: + if (curByte & 0x80) { + command = curByte; + curChannel = command & 0x0F; + midiParamCount = nMidiParams[(command >> 4) - 8]; + } + } + if ((1 << curChannel) & channelMask) { + if (command != kEndOfTrack) { + // Write delta + while (delta > 240) { + *outData++ = 0xF8; + delta -= 240; + } + *outData++ = (byte)delta; + delta = 0; + } + // Write command + switch (command) { + case 0xF0: // sysEx + *outData++ = command; + do { + curByte = *channelData++; + *outData++ = curByte; // out + } while (curByte != 0xF7); + lastCommand = command; + break; + + case kEndOfTrack: // end of channel + break; + + default: // MIDI command + // remember which channel got used for channel remapping + byte midiChannel = command & 0xF; + _channelUsed[midiChannel] = true; + + if (lastCommand != command) { + *outData++ = command; + lastCommand = command; + } + if (midiParamCount > 0) { + if (curByte & 0x80) + *outData++ = *channelData++; + else + *outData++ = curByte; + } + if (midiParamCount > 1) { + *outData++ = *channelData++; + } + } + } else { + if (curByte & 0x80) + channelData += midiParamCount; + else + channelData += midiParamCount - 1; + } + } + + // Insert stop event + *outData++ = 0; // Delta + *outData++ = 0xFF; // Meta event + *outData++ = 0x2F; // End of track (EOT) + *outData++ = 0x00; + *outData++ = 0x00; + + return _mixedData; +} + +// This will get called right before actual playing and will try to own the used channels +void MidiParser_SCI::tryToOwnChannels() { + // We don't have SciMusic in case debug command show_instruments is used + if (!_music) + return; + for (int curChannel = 0; curChannel < 15; curChannel++) { + if (_channelUsed[curChannel]) { + if (_channelRemap[curChannel] == -1) { + _channelRemap[curChannel] = _music->tryToOwnChannel(_pSnd, curChannel); + } + } + } +} + +void MidiParser_SCI::lostChannels() { + for (int curChannel = 0; curChannel < 15; curChannel++) + if ((_channelUsed[curChannel]) && (curChannel != 9)) + _channelRemap[curChannel] = -1; +} + +void MidiParser_SCI::sendInitCommands() { + // reset our "global" volume and channel volumes + _volume = 127; + for (int i = 0; i < 16; i++) + _channelVolume[i] = 127; + + // Set initial voice count + if (_pSnd) { + if (_soundVersion <= SCI_VERSION_0_LATE) { + for (int i = 0; i < 15; ++i) { + byte voiceCount = 0; + if (_channelUsed[i]) { + voiceCount = _pSnd->soundRes->getInitialVoiceCount(i); + sendToDriver(0xB0 | i, 0x4B, voiceCount); + } + } } } // Send a velocity off signal to all channels - for (int i = 0; i < 16; ++i) { - _driver->send(0xB0 | i, 0x4E, 0); // Reset velocity + for (int i = 0; i < 15; ++i) { + if (_channelUsed[i]) + sendToDriver(0xB0 | i, 0x4E, 0); // Reset velocity } - return true; + // Center the pitch wheels and hold pedal in preparation for the next piece of music + for (int i = 0; i < 16; ++i) { + if (_channelUsed[i]) { + sendToDriver(0xE0 | i, 0, 0x40); // Reset pitch wheel + sendToDriver(0xB0 | i, 0x40, 0); // Reset hold pedal + } + } } void MidiParser_SCI::unloadMusic() { - resetTracking(); - allNotesOff(); + if (_pSnd) { + resetTracking(); + allNotesOff(); + } _num_tracks = 0; _active_track = 255; _resetOnPause = false; @@ -118,36 +376,76 @@ void MidiParser_SCI::unloadMusic() { delete[] _mixedData; _mixedData = NULL; } +} - // Center the pitch wheels and hold pedal in preparation for the next piece of music - if (_driver) { - for (int i = 0; i < 16; ++i) { - if (isChannelUsed(i)) { - _driver->send(0xE0 | i, 0, 0x40); // Reset pitch wheel - _driver->send(0xB0 | i, 0x40, 0); // Reset hold pedal - } +// this is used for scripts sending midi commands to us. we verify in that case that the channel is actually +// used, so that channel remapping will work as well and then send them on +void MidiParser_SCI::sendFromScriptToDriver(uint32 midi) { + byte midiChannel = midi & 0xf; + + if (!_channelUsed[midiChannel]) { + // trying to send to an unused channel + // this happens for cmdSendMidi at least in sq1vga right at the start, it's a script issue + return; + } + if (_channelRemap[midiChannel] == -1) { + // trying to send to an unmapped channel + // this happens for cmdSendMidi at least in sq1vga right at the start, scripts are pausing the sound + // and then sending manually. it's a script issue + return; + } + sendToDriver(midi); +} + +void MidiParser_SCI::sendToDriver(uint32 midi) { + byte midiChannel = midi & 0xf; + + if ((midi & 0xFFF0) == 0x4EB0) { + // this is channel mute only for sci1 + // it's velocity control for sci0 + if (_soundVersion >= SCI_VERSION_1_EARLY) { + _channelMuted[midiChannel] = midi & 0xFF0000 ? true : false; + return; // don't send this to driver at all } } - for (int i = 0; i < 16; i++) - _channelRemap[i] = i; + // Is channel muted? if so, don't send command + if (_channelMuted[midiChannel]) + return; + + if ((midi & 0xFFF0) == 0x07B0) { + // someone trying to set channel volume? + int channelVolume = (midi >> 16) & 0xFF; + // Remember, if we need to set it ourselves + _channelVolume[midiChannel] = channelVolume; + // Adjust volume accordingly to current "global" volume + channelVolume = channelVolume * _volume / 127; + midi = (midi & 0xFFF0) | ((channelVolume & 0xFF) << 16); + } + + // Channel remapping + int16 realChannel = _channelRemap[midiChannel]; + assert(realChannel != -1); + + midi = (midi & 0xFFFFFFF0) | realChannel; + if (_mainThreadCalled) + _music->putMidiCommandInQueue(midi); + else + _driver->send(midi); } void MidiParser_SCI::parseNextEvent(EventInfo &info) { - // Monitor which channels are used by this song - setChannelUsed(info.channel()); - // Set signal AFTER waiting for delta, otherwise we would set signal too soon resulting in all sorts of bugs if (_dataincAdd) { _dataincAdd = false; _pSnd->dataInc += _dataincToAdd; _pSnd->signal = 0x7f + _pSnd->dataInc; - debugC(2, kDebugLevelSound, "datainc %04x", _dataincToAdd); + debugC(4, kDebugLevelSound, "datainc %04x", _dataincToAdd); } if (_signalSet) { _signalSet = false; _pSnd->signal = _signalToSet; - debugC(2, kDebugLevelSound, "signal %04x", _signalToSet); + debugC(4, kDebugLevelSound, "signal %04x", _signalToSet); } info.start = _position._play_pos; @@ -173,10 +471,16 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { info.basic.param2 = 0; if (info.channel() == 0xF) {// SCI special case if (info.basic.param1 != kSetSignalLoop) { - _signalSet = true; - _signalToSet = info.basic.param1; + // at least in kq5/french&mac the first scene in the intro has a song that sets signal to 4 immediately + // on tick 0. Signal isn't set at that point by sierra sci and it would cause the castle daventry text to + // get immediately removed, so we currently filter it. + // Sierra SCI ignores them as well at that time + if (_position._play_tick) { + _signalSet = true; + _signalToSet = info.basic.param1; + } } else { - _loopTick = _position._play_tick; + _loopTick = _position._play_tick + info.delta; } } break; @@ -235,7 +539,6 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { case 0x0A: // pan case 0x0B: // expression case 0x40: // sustain - case 0x4E: // velocity control case 0x79: // reset all case 0x7B: // notes off // These are all handled by the music driver, so ignore them @@ -249,8 +552,6 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { break; } } - if (info.basic.param1 == 7) // channel volume change -scale it - info.basic.param2 = info.basic.param2 * _volume / MUSIC_VOLUME_MAX; info.length = 0; break; @@ -307,7 +608,7 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { _pSnd->status = kSoundStopped; _pSnd->signal = SIGNAL_OFFSET; - debugC(2, kDebugLevelSound, "signal EOT"); + debugC(4, kDebugLevelSound, "signal EOT"); } } break; @@ -319,254 +620,66 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { }// switch (info.command()) } +void MidiParser_SCI::allNotesOff() { + if (!_driver) + return; -byte MidiParser_SCI::midiGetNextChannel(long ticker) { - byte curr = 0xFF; - long closest = ticker + 1000000, next = 0; - - for (int i = 0; i < _track->channelCount; i++) { - if (_track->channels[i].time == -1) // channel ended - continue; - next = *_track->channels[i].data; // when the next event should occur - if (next == 0xF8) // 0xF8 means 240 ticks delay - next = 240; - next += _track->channels[i].time; - if (next < closest) { - curr = i; - closest = next; - } - } - - return curr; -} - -byte *MidiParser_SCI::midiMixChannels() { - int totalSize = 0; - byte **dataPtr = new byte *[_track->channelCount]; - - for (int i = 0; i < _track->channelCount; i++) { - dataPtr[i] = _track->channels[i].data; - _track->channels[i].time = 0; - _track->channels[i].prev = 0; - totalSize += _track->channels[i].size; - } - - byte *outData = new byte[totalSize * 2]; // FIXME: creates overhead and still may be not enough to hold all data - _mixedData = outData; - long ticker = 0; - byte curr, curDelta; - byte command = 0, par1, global_prev = 0; - long new_delta; - SoundResource::Channel *channel; - - while ((curr = midiGetNextChannel(ticker)) != 0xFF) { // there is still active channel - channel = &_track->channels[curr]; - curDelta = *channel->data++; - channel->time += (curDelta == 0xF8 ? 240 : curDelta); // when the comamnd is supposed to occur - if (curDelta == 0xF8) - continue; - new_delta = channel->time - ticker; - ticker += new_delta; - - command = *channel->data++; - if (command != kEndOfTrack) { - debugC(2, kDebugLevelSound, "\nDELTA "); - // Write delta - while (new_delta > 240) { - *outData++ = 0xF8; - debugC(2, kDebugLevelSound, "F8 "); - new_delta -= 240; - } - *outData++ = (byte)new_delta; - debugC(2, kDebugLevelSound, "%02X ", (uint32)new_delta); - } - // Write command - switch (command) { - case 0xF0: // sysEx - *outData++ = command; - debugC(2, kDebugLevelSound, "%02X ", command); - do { - par1 = *channel->data++; - *outData++ = par1; // out - } while (par1 != 0xF7); - break; - case kEndOfTrack: // end of channel - channel->time = -1; // FIXME - break; - default: // MIDI command - if (command & 0x80) { - par1 = *channel->data++; - - // TODO: Fix remapping + int i, j; -#if 0 - // Remap channel. Keep the upper 4 bits (command code) and change - // the lower 4 bits (channel) - byte remappedChannel = _channelRemap[par1 & 0xF]; - par1 = (par1 & 0xF0) | (remappedChannel & 0xF); -#endif - } else {// running status - par1 = command; - command = channel->prev; + // Turn off all active notes + for (i = 0; i < 128; ++i) { + for (j = 0; j < 16; ++j) { + if ((_active_notes[i] & (1 << j)) && (_channelRemap[j] != -1)){ + sendToDriver(0x80 | j, i, 0); } - if (command != global_prev) - *outData++ = command; // out command - *outData++ = par1;// pout par1 - if (nMidiParams[(command >> 4) - 8] == 2) - *outData++ = *channel->data++; // out par2 - channel->prev = command; - global_prev = command; - }// switch(command) - }// while (curr) - - // Insert stop event - *outData++ = 0; // Delta - *outData++ = 0xFF; // Meta event - *outData++ = 0x2F; // End of track (EOT) - *outData++ = 0x00; - *outData++ = 0x00; - - for (int channelNr = 0; channelNr < _track->channelCount; channelNr++) - _track->channels[channelNr].data = dataPtr[channelNr]; - - delete[] dataPtr; - return _mixedData; -} - -// This is used for SCI0 sound-data. SCI0 only has one stream that may -// contain several channels and according to output device we remove -// certain channels from that data. -byte *MidiParser_SCI::midiFilterChannels(int channelMask) { - SoundResource::Channel *channel = &_track->channels[0]; - byte *channelData = channel->data; - byte *channelDataEnd = channel->data + channel->size; - byte *outData = new byte[channel->size + 5]; - byte curChannel = 15, curByte, curDelta; - byte command = 0, lastCommand = 0; - int delta = 0; - int midiParamCount = 0; - - _mixedData = outData; - - while (channelData < channelDataEnd) { - curDelta = *channelData++; - if (curDelta == 0xF8) { - delta += 240; - continue; } - delta += curDelta; - curByte = *channelData++; + } - switch (curByte) { - case 0xF0: // sysEx - case kEndOfTrack: // end of channel - command = curByte; - curChannel = 15; - break; - default: - if (curByte & 0x80) { - command = curByte; - curChannel = command & 0x0F; - midiParamCount = nMidiParams[(command >> 4) - 8]; - } + // Turn off all hanging notes + for (i = 0; i < ARRAYSIZE(_hanging_notes); i++) { + byte midiChannel = _hanging_notes[i].channel; + if ((_hanging_notes[i].time_left) && (_channelRemap[midiChannel] != -1)) { + sendToDriver(0x80 | midiChannel, _hanging_notes[i].note, 0); + _hanging_notes[i].time_left = 0; } - if ((1 << curChannel) & channelMask) { - if (command != kEndOfTrack) { - debugC(2, kDebugLevelSound, "\nDELTA "); - // Write delta - while (delta > 240) { - *outData++ = 0xF8; - debugC(2, kDebugLevelSound, "F8 "); - delta -= 240; - } - *outData++ = (byte)delta; - debugC(2, kDebugLevelSound, "%02X ", delta); - delta = 0; - } - // Write command - switch (command) { - case 0xF0: // sysEx - *outData++ = command; - debugC(2, kDebugLevelSound, "%02X ", command); - do { - curByte = *channelData++; - *outData++ = curByte; // out - } while (curByte != 0xF7); - lastCommand = command; - break; + } + _hanging_notes_count = 0; - case kEndOfTrack: // end of channel - break; + // To be sure, send an "All Note Off" event (but not all MIDI devices + // support this...). - default: // MIDI command - if (lastCommand != command) { - *outData++ = command; - debugC(2, kDebugLevelSound, "%02X ", command); - lastCommand = command; - } - if (midiParamCount > 0) { - if (curByte & 0x80) { - debugC(2, kDebugLevelSound, "%02X ", *channelData); - *outData++ = *channelData++; - } else { - debugC(2, kDebugLevelSound, "%02X ", curByte); - *outData++ = curByte; - } - } - if (midiParamCount > 1) { - debugC(2, kDebugLevelSound, "%02X ", *channelData); - *outData++ = *channelData++; - } - } - } else { - if (curByte & 0x80) { - channelData += midiParamCount; - } else { - channelData += midiParamCount - 1; - } - } + for (i = 0; i < 16; ++i) { + if (_channelRemap[i] != -1) + sendToDriver(0xB0 | i, 0x7b, 0); // All notes off } - // Insert stop event - *outData++ = 0; // Delta - *outData++ = 0xFF; // Meta event - *outData++ = 0x2F; // End of track (EOT) - *outData++ = 0x00; - *outData++ = 0x00; - - return _mixedData; + memset(_active_notes, 0, sizeof(_active_notes)); } void MidiParser_SCI::setVolume(byte volume) { - // FIXME: This receives values > 127... throw a warning for now and clip the variable - if (volume > MUSIC_VOLUME_MAX) { - warning("attempted to set an invalid volume(%d)", volume); - volume = MUSIC_VOLUME_MAX; // reset - } - assert(volume <= MUSIC_VOLUME_MAX); - if (_volume != volume) { - _volume = volume; - - switch (_soundVersion) { - case SCI_VERSION_0_EARLY: - case SCI_VERSION_0_LATE: { - int16 globalVolume = _volume * 15 / 127; - ((MidiPlayer *)_driver)->setVolume(globalVolume); - break; - } + _volume = volume; + + switch (_soundVersion) { + case SCI_VERSION_0_EARLY: + case SCI_VERSION_0_LATE: { + // SCI0 adlib driver doesn't support channel volumes, so we need to go this way + // TODO: this should take the actual master volume into account + int16 globalVolume = _volume * 15 / 127; + ((MidiPlayer *)_driver)->setVolume(globalVolume); + break; + } - case SCI_VERSION_1_EARLY: - case SCI_VERSION_1_LATE: - // sending volume change to all active channels - for (int i = 0; i < _track->channelCount; i++) - if (_track->channels[i].number <= 0xF) - _driver->send(0xB0 + _track->channels[i].number, 7, _volume); - break; + case SCI_VERSION_1_EARLY: + case SCI_VERSION_1_LATE: + // Send previous channel volumes again to actually update the volume + for (int i = 0; i < 15; i++) + if (_channelRemap[i] != -1) + sendToDriver(0xB0 + i, 7, _channelVolume[i]); + break; - default: - error("MidiParser_SCI::setVolume: Unsupported soundVersion"); - } + default: + error("MidiParser_SCI::setVolume: Unsupported soundVersion"); } } diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h index 9d4b5a39da..90db06e539 100644 --- a/engines/sci/sound/midiparser_sci.h +++ b/engines/sci/sound/midiparser_sci.h @@ -53,12 +53,17 @@ namespace Sci { */ class MidiParser_SCI : public MidiParser { public: - MidiParser_SCI(SciVersion soundVersion); + MidiParser_SCI(SciVersion soundVersion, SciMusic *music); ~MidiParser_SCI(); + + void mainThreadBegin(); + void mainThreadEnd(); + bool loadMusic(SoundResource::Track *track, MusicEntry *psnd, int channelFilterMask, SciVersion soundVersion); bool loadMusic(byte *, uint32) { return false; } + void sendInitCommands(); void unloadMusic(); void setVolume(byte volume); void stop() { @@ -71,23 +76,29 @@ public: jumpToTick(0); } - void remapChannel(byte channel, byte newChannel) { - assert(channel < 0xF); // don't touch special SCI channel 15 - assert(newChannel < 0xF); // don't touch special SCI channel 15 - _channelRemap[channel] = newChannel; - } + void allNotesOff(); - void clearUsedChannels() { _channelsUsed = 0; } + const byte *getMixedData() const { return _mixedData; } -protected: - bool isChannelUsed(byte channel) const { return _channelsUsed & (1 << channel); } - void setChannelUsed(byte channel) { _channelsUsed |= (1 << channel); } + void tryToOwnChannels(); + void lostChannels(); + void sendFromScriptToDriver(uint32 midi); + void sendToDriver(uint32 midi); + void sendToDriver(byte status, byte firstOp, byte secondOp) { + sendToDriver(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16)); + } +protected: void parseNextEvent(EventInfo &info); byte *midiMixChannels(); byte *midiFilterChannels(int channelMask); byte midiGetNextChannel(long ticker); + SciMusic *_music; + + // this is set, when main thread calls us -> we send commands to queue instead to driver + bool _mainThreadCalled; + SciVersion _soundVersion; byte *_mixedData; SoundResource::Track *_track; @@ -101,11 +112,10 @@ protected: int16 _dataincToAdd; bool _resetOnPause; - // A 16-bit mask, containing the channels used - // by the currently parsed song - uint16 _channelsUsed; - - byte _channelRemap[16]; + bool _channelUsed[16]; + int16 _channelRemap[16]; + bool _channelMuted[16]; + byte _channelVolume[16]; }; } // End of namespace Sci diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index fa5716e7cc..55a7e1fdc4 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -43,6 +43,11 @@ SciMusic::SciMusic(SciVersion soundVersion) // Reserve some space in the playlist, to avoid expensive insertion // operations _playList.reserve(10); + + for (int i = 0; i < 16; i++) + _usedChannel[i] = 0; + + _queuedCommands.reserve(1000); } SciMusic::~SciMusic() { @@ -58,31 +63,30 @@ void SciMusic::init() { // SCI sound init _dwTempo = 0; - MidiDriverType midiType; - // Default to MIDI in SCI32 games, as many don't have AdLib support. - // WORKAROUND: Default to MIDI in Amiga SCI1_EGA+ games as we don't support those patches yet. - // We also don't yet support the 7.pat file of SCI1+ Mac games or SCI0 Mac patches, so we - // default to MIDI in those games to let them run. + // WORKAROUND: Default to MIDI in Amiga SCI1_EGA+ games as we don't support + // those patches yet. We also don't yet support the 7.pat file of SCI1+ Mac + // games or SCI0 Mac patches, so we default to MIDI in those games to let + // them run. Common::Platform platform = g_sci->getPlatform(); - - if (getSciVersion() >= SCI_VERSION_2 || platform == Common::kPlatformMacintosh || (platform == Common::kPlatformAmiga && getSciVersion() >= SCI_VERSION_1_EGA)) - midiType = MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI); - else - midiType = MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_ADLIB | MDT_MIDI); - - switch (midiType) { - case MD_ADLIB: + uint32 dev = MidiDriver::detectDevice( + (getSciVersion() >= SCI_VERSION_2 || platform == Common::kPlatformMacintosh || + (platform == Common::kPlatformAmiga && getSciVersion() >= SCI_VERSION_1_EGA)) + ? (MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM) + : (MDT_PCSPK | MDT_ADLIB | MDT_MIDI)); + + switch (MidiDriver::getMusicType(dev)) { + case MT_ADLIB: // FIXME: There's no Amiga sound option, so we hook it up to AdLib if (g_sci->getPlatform() == Common::kPlatformAmiga) _pMidiDrv = MidiPlayer_Amiga_create(_soundVersion); else _pMidiDrv = MidiPlayer_AdLib_create(_soundVersion); break; - case MD_PCJR: + case MT_PCJR: _pMidiDrv = MidiPlayer_PCJr_create(_soundVersion); break; - case MD_PCSPK: + case MT_PCSPK: _pMidiDrv = MidiPlayer_PCSpeaker_create(_soundVersion); break; default: @@ -100,6 +104,49 @@ void SciMusic::init() { } _bMultiMidi = ConfMan.getBool("multi_midi"); + + // Find out what the first possible channel is (used, when doing channel + // remapping). + _driverFirstChannel = _pMidiDrv->getFirstChannel(); +} + +void SciMusic::miditimerCallback(void *p) { + SciMusic *sciMusic = (SciMusic *)p; + + Common::StackLock lock(sciMusic->_mutex); + sciMusic->onTimer(); +} + +void SciMusic::onTimer() { + const MusicList::iterator end = _playList.end(); + // sending out queued commands that were "sent" via main thread + sendMidiCommandsFromQueue(); + + for (MusicList::iterator i = _playList.begin(); i != end; ++i) + (*i)->onTimer(); +} + +void SciMusic::putMidiCommandInQueue(byte status, byte firstOp, byte secondOp) { + putMidiCommandInQueue(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16)); +} + +void SciMusic::putMidiCommandInQueue(uint32 midi) { + _queuedCommands.push_back(midi); +} + +// This sends the stored commands from queue to driver (is supposed to get +// called only during onTimer()). At least mt32 emulation doesn't like getting +// note-on commands from main thread (if we directly send, we would get a crash +// during piano scene in lsl5). +void SciMusic::sendMidiCommandsFromQueue() { + uint curCommand = 0; + uint commandCount = _queuedCommands.size(); + + while (curCommand < commandCount) { + _pMidiDrv->send(_queuedCommands[curCommand]); + curCommand++; + } + _queuedCommands.clear(); } void SciMusic::clearPlayList() { @@ -119,22 +166,12 @@ void SciMusic::pauseAll(bool pause) { } void SciMusic::stopAll() { - Common::StackLock lock(_mutex); - const MusicList::iterator end = _playList.end(); for (MusicList::iterator i = _playList.begin(); i != end; ++i) { soundStop(*i); } } - -void SciMusic::miditimerCallback(void *p) { - SciMusic *aud = (SciMusic *)p; - - Common::StackLock lock(aud->_mutex); - aud->onTimer(); -} - void SciMusic::soundSetSoundOn(bool soundOnFlag) { Common::StackLock lock(_mutex); @@ -160,6 +197,24 @@ MusicEntry *SciMusic::getSlot(reg_t obj) { return NULL; } +// We return the currently active music slot for SCI0 +MusicEntry *SciMusic::getActiveSci0MusicSlot() { + const MusicList::iterator end = _playList.end(); + MusicEntry *highestPrioritySlot = NULL; + for (MusicList::iterator i = _playList.begin(); i != end; ++i) { + MusicEntry *playSlot = *i; + if (playSlot->pMidiParser) { + if (playSlot->status == kSoundPlaying) + return playSlot; + if (playSlot->status == kSoundPaused) { + if ((!highestPrioritySlot) || (highestPrioritySlot->priority < playSlot->priority)) + highestPrioritySlot = playSlot; + } + } + } + return highestPrioritySlot; +} + void SciMusic::setReverb(byte reverb) { Common::StackLock lock(_mutex); _pMidiDrv->setReverb(reverb); @@ -174,28 +229,14 @@ void SciMusic::sortPlayList() { Common::sort(_playList.begin(), _playList.end(), musicEntryCompare); } -void SciMusic::findUsedChannels() { - // Reset list - for (int k = 0; k < 16; k++) - _usedChannels[k] = false; - - const MusicList::const_iterator end = _playList.end(); - for (MusicList::const_iterator i = _playList.begin(); i != end; ++i) { - for (int channel = 0; channel < 16; channel++) { - if ((*i)->soundRes && (*i)->soundRes->isChannelUsed(channel)) - _usedChannels[channel] = true; - } - } -} - void SciMusic::soundInitSnd(MusicEntry *pSnd) { int channelFilterMask = 0; SoundResource::Track *track = pSnd->soundRes->getTrackByType(_pMidiDrv->getPlayId()); - // If MIDI device is selected but there is no digital track in sound resource - // try to use adlib's digital sample if possible - // Also, if the track couldn't be found, load the digital track, as some games - // depend on this (e.g. the Longbow demo) + // If MIDI device is selected but there is no digital track in sound + // resource try to use adlib's digital sample if possible. Also, if the + // track couldn't be found, load the digital track, as some games depend on + // this (e.g. the Longbow demo). if (!track || (_bMultiMidi && track->digitalChannelNr == -1)) { SoundResource::Track *digital = pSnd->soundRes->getDigitalTrack(); if (digital) @@ -224,49 +265,53 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { _mutex.lock(); pSnd->soundType = Audio::Mixer::kMusicSoundType; if (pSnd->pMidiParser == NULL) { - pSnd->pMidiParser = new MidiParser_SCI(_soundVersion); + pSnd->pMidiParser = new MidiParser_SCI(_soundVersion, this); pSnd->pMidiParser->setMidiDriver(_pMidiDrv); pSnd->pMidiParser->setTimerRate(_dwTempo); } pSnd->pauseCounter = 0; - // TODO: Fix channel remapping. This doesn't quite work... (e.g. no difference in LSL1VGA) -#if 0 - // Remap channels - findUsedChannels(); - - pSnd->pMidiParser->clearUsedChannels(); - - for (int i = 0; i < 16; i++) { - if (_usedChannels[i] && pSnd->soundRes->isChannelUsed(i)) { - int16 newChannel = getNextUnusedChannel(); - if (newChannel >= 0) { - _usedChannels[newChannel] = true; - debug("Remapping channel %d to %d\n", i, newChannel); - pSnd->pMidiParser->remapChannel(i, newChannel); - } else { - warning("Attempt to remap channel %d, but no unused channels exist", i); - } - } - } -#endif - // Find out what channels to filter for SCI0 channelFilterMask = pSnd->soundRes->getChannelFilterMask(_pMidiDrv->getPlayId(), _pMidiDrv->hasRhythmChannel()); - pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion); - // Fast forward to the last position and perform associated events when loading - pSnd->pMidiParser->jumpToTick(pSnd->ticker, true); + pSnd->pMidiParser->mainThreadBegin(); + pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion); + pSnd->pMidiParser->mainThreadEnd(); _mutex.unlock(); } } } -void SciMusic::onTimer() { - const MusicList::iterator end = _playList.end(); - for (MusicList::iterator i = _playList.begin(); i != end; ++i) - (*i)->onTimer(); +// This one checks, if requested channel is available -> in that case give +// caller that channel. Otherwise look for an unused one +int16 SciMusic::tryToOwnChannel(MusicEntry *caller, int16 bestChannel) { + // Don't even try this for SCI0 + if (_soundVersion <= SCI_VERSION_0_LATE) + return bestChannel; + if (!_usedChannel[bestChannel]) { + // currently unused, so give it to caller directly + _usedChannel[bestChannel] = caller; + return bestChannel; + } + // otherwise look for unused channel + for (int channelNr = _driverFirstChannel; channelNr < 15; channelNr++) { + if (!_usedChannel[channelNr]) { + _usedChannel[channelNr] = caller; + return channelNr; + } + } + error("no free channels"); +} + +void SciMusic::freeChannels(MusicEntry *caller) { + // Remove used channels + for (int i = 0; i < 15; i++) { + if (_usedChannel[i] == caller) + _usedChannel[i] = 0; + } + // Also tell midiparser, that he lost ownership + caller->pMidiParser->lostChannels(); } void SciMusic::soundPlay(MusicEntry *pSnd) { @@ -294,7 +339,7 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { if ((_soundVersion <= SCI_VERSION_0_LATE) && (alreadyPlaying)) { // Music already playing in SCI0? if (pSnd->priority > alreadyPlaying->priority) { - // And new priority higher? pause previous music and play new one immediately + // And new priority higher? pause previous music and play new one immediately. // Example of such case: lsl3, when getting points (jingle is played then) soundPause(alreadyPlaying); alreadyPlaying->isQueued = true; @@ -317,34 +362,54 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { pSnd->pLoopStream, -1, pSnd->volume, 0, DisposeAfterUse::NO); } else { + // Rewind in case we play the same sample multiple times + // (non-looped) like in pharkas right at the start + pSnd->pStreamAud->rewind(); _pMixer->playStream(pSnd->soundType, &pSnd->hCurrentAud, pSnd->pStreamAud, -1, pSnd->volume, 0, DisposeAfterUse::NO); } } else { - _mutex.lock(); if (pSnd->pMidiParser) { - pSnd->pMidiParser->setVolume(pSnd->volume); + _mutex.lock(); + pSnd->pMidiParser->mainThreadBegin(); + pSnd->pMidiParser->tryToOwnChannels(); if (pSnd->status == kSoundStopped) + pSnd->pMidiParser->sendInitCommands(); + pSnd->pMidiParser->setVolume(pSnd->volume); + if (pSnd->status == kSoundStopped) { pSnd->pMidiParser->jumpToTick(0); + } else { + // Fast forward to the last position and perform associated events when loading + pSnd->pMidiParser->jumpToTick(pSnd->ticker, true); + } + pSnd->pMidiParser->mainThreadEnd(); + _mutex.unlock(); } - _mutex.unlock(); } pSnd->status = kSoundPlaying; } void SciMusic::soundStop(MusicEntry *pSnd) { + SoundStatus previousStatus = pSnd->status; pSnd->status = kSoundStopped; if (_soundVersion <= SCI_VERSION_0_LATE) pSnd->isQueued = false; if (pSnd->pStreamAud) _pMixer->stopHandle(pSnd->hCurrentAud); - _mutex.lock(); - if (pSnd->pMidiParser) - pSnd->pMidiParser->stop(); - _mutex.unlock(); + if (pSnd->pMidiParser) { + _mutex.lock(); + pSnd->pMidiParser->mainThreadBegin(); + // We shouldn't call stop in case it's paused, otherwise we would send + // allNotesOff() again + if (previousStatus == kSoundPlaying) + pSnd->pMidiParser->stop(); + freeChannels(pSnd); + pSnd->pMidiParser->mainThreadEnd(); + _mutex.unlock(); + } } void SciMusic::soundSetVolume(MusicEntry *pSnd, byte volume) { @@ -353,7 +418,9 @@ void SciMusic::soundSetVolume(MusicEntry *pSnd, byte volume) { _pMixer->setChannelVolume(pSnd->hCurrentAud, volume * 2); // Mixer is 0-255, SCI is 0-127 } else if (pSnd->pMidiParser) { _mutex.lock(); + pSnd->pMidiParser->mainThreadBegin(); pSnd->pMidiParser->setVolume(volume); + pSnd->pMidiParser->mainThreadEnd(); _mutex.unlock(); } } @@ -368,13 +435,15 @@ void SciMusic::soundSetPriority(MusicEntry *pSnd, byte prio) { void SciMusic::soundKill(MusicEntry *pSnd) { pSnd->status = kSoundStopped; - _mutex.lock(); if (pSnd->pMidiParser) { + _mutex.lock(); + pSnd->pMidiParser->mainThreadBegin(); pSnd->pMidiParser->unloadMusic(); + pSnd->pMidiParser->mainThreadEnd(); delete pSnd->pMidiParser; pSnd->pMidiParser = NULL; + _mutex.unlock(); } - _mutex.unlock(); if (pSnd->pStreamAud) { _pMixer->stopHandle(pSnd->hCurrentAud); @@ -406,10 +475,14 @@ void SciMusic::soundPause(MusicEntry *pSnd) { if (pSnd->pStreamAud) { _pMixer->pauseHandle(pSnd->hCurrentAud, true); } else { - _mutex.lock(); - if (pSnd->pMidiParser) + if (pSnd->pMidiParser) { + _mutex.lock(); + pSnd->pMidiParser->mainThreadBegin(); pSnd->pMidiParser->pause(); - _mutex.unlock(); + freeChannels(pSnd); + pSnd->pMidiParser->mainThreadEnd(); + _mutex.unlock(); + } } } @@ -448,6 +521,21 @@ void SciMusic::soundSetMasterVolume(uint16 vol) { _pMidiDrv->setVolume(vol); } +void SciMusic::sendMidiCommand(uint32 cmd) { + Common::StackLock lock(_mutex); + _pMidiDrv->send(cmd); +} + +void SciMusic::sendMidiCommand(MusicEntry *pSnd, uint32 cmd) { + Common::StackLock lock(_mutex); + if (!pSnd->pMidiParser) + error("tried to cmdSendMidi on non midi slot (%04x:%04x)", PRINT_REG(pSnd->soundObj)); + + pSnd->pMidiParser->mainThreadBegin(); + pSnd->pMidiParser->sendFromScriptToDriver(cmd); + pSnd->pMidiParser->mainThreadEnd(); +} + void SciMusic::printPlayList(Console *con) { Common::StackLock lock(_mutex); @@ -567,14 +655,6 @@ void MusicEntry::doFade() { fadeStep = 0; fadeCompleted = true; } -#ifdef ENABLE_SCI32 - // Disable fading for SCI32 - sound drivers have issues when fading in (gabriel knight 1 sierra title) - if (getSciVersion() >= SCI_VERSION_2) { - volume = fadeTo; - fadeStep = 0; - fadeCompleted = true; - } -#endif // Only process MIDI streams in this thread, not digital sound effects if (pMidiParser) { diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index 83cd59e89b..943a5bd2a8 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -26,15 +26,11 @@ #ifndef SCI_MUSIC_H #define SCI_MUSIC_H -#ifndef USE_OLD_MUSIC_FUNCTIONS #include "common/serializer.h" -#endif #include "common/mutex.h" #include "sound/mixer.h" #include "sound/audiostream.h" -//#include "sound/mididrv.h" -//#include "sound/midiparser.h" #include "sci/sci.h" #include "sci/resource.h" @@ -55,11 +51,7 @@ enum SoundStatus { class MidiParser_SCI; class SegManager; -class MusicEntry -#ifndef USE_OLD_MUSIC_FUNCTIONS - : public Common::Serializable -#endif -{ +class MusicEntry : public Common::Serializable { public: // Do not get these directly for the sound objects! // It's a bad idea, as the sound code (i.e. the SciMusic @@ -96,9 +88,6 @@ public: Audio::Mixer::SoundType soundType; -#ifndef USE_OLD_MUSIC_FUNCTIONS -//protected: -#endif MidiParser_SCI *pMidiParser; // TODO: We need to revise how we store the different @@ -114,25 +103,28 @@ public: void doFade(); void onTimer(); -#ifndef USE_OLD_MUSIC_FUNCTIONS virtual void saveLoadWithSerializer(Common::Serializer &ser); -#endif }; typedef Common::Array<MusicEntry *> MusicList; +typedef Common::Array<uint32> MidiCommandQueue; -class SciMusic -#ifndef USE_OLD_MUSIC_FUNCTIONS - : public Common::Serializable -#endif -{ +class SciMusic : public Common::Serializable { public: SciMusic(SciVersion soundVersion); ~SciMusic(); void init(); + void onTimer(); + void putMidiCommandInQueue(byte status, byte firstOp, byte secondOp); + void putMidiCommandInQueue(uint32 midi); +private: + static void miditimerCallback(void *p); + void sendMidiCommandsFromQueue(); + +public: void clearPlayList(); void pauseAll(bool pause); void stopAll(); @@ -165,6 +157,7 @@ public: } MusicEntry *getSlot(reg_t obj); + MusicEntry *getActiveSci0MusicSlot(); void pushBackSlot(MusicEntry *slotEntry) { Common::StackLock lock(_mutex); @@ -179,16 +172,12 @@ public: MusicList::iterator getPlayListStart() { return _playList.begin(); } MusicList::iterator getPlayListEnd() { return _playList.end(); } - void sendMidiCommand(uint32 cmd) { - Common::StackLock lock(_mutex); - _pMidiDrv->send(cmd); - } + void sendMidiCommand(uint32 cmd); + void sendMidiCommand(MusicEntry *pSnd, uint32 cmd); void setReverb(byte reverb); -#ifndef USE_OLD_MUSIC_FUNCTIONS virtual void saveLoadWithSerializer(Common::Serializer &ser); -#endif // Mutex for music code. Used to guard access to the song playlist, to the // MIDI parser and to the MIDI driver/player. Note that guarded code must NOT @@ -196,6 +185,9 @@ public: // where a deadlock can occur Common::Mutex _mutex; + int16 tryToOwnChannel(MusicEntry *caller, int16 bestChannel); + void freeChannels(MusicEntry *caller); + protected: void sortPlayList(); @@ -208,22 +200,16 @@ protected: // Mixed AdLib/MIDI mode: when enabled from the ScummVM sound options screen, // and a sound has a digital track, the sound from the AdLib track is played bool _bMultiMidi; -private: - static void miditimerCallback(void *p); - void findUsedChannels(); - int16 getNextUnusedChannel() const { - for (int i = 0; i < 16; i++) { - if (!_usedChannels[i]) - return i; - } - - return -1; - } +private: MusicList _playList; bool _soundOn; byte _masterVolume; - bool _usedChannels[16]; + MusicEntry *_usedChannel[16]; + + MidiCommandQueue _queuedCommands; + + int _driverFirstChannel; }; } // End of namespace Sci diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index ece4c1430c..51832af09f 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -23,17 +23,12 @@ * */ -#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS - -#ifdef USE_OLD_MUSIC_FUNCTIONS -#include "sci/sound/iterator/iterator.h" // for SongIteratorStatus -#endif - #include "common/config-manager.h" #include "sci/sound/audio.h" #include "sci/sound/music.h" #include "sci/sound/soundcmd.h" +#include "sci/engine/kernel.h" #include "sci/engine/selector.h" namespace Sci { @@ -41,258 +36,29 @@ namespace Sci { #define SCI1_SOUND_FLAG_MAY_PAUSE 1 /* Only here for completeness; The interpreter doesn't touch this bit */ #define SCI1_SOUND_FLAG_SCRIPTED_PRI 2 /* but does touch this */ -#ifdef USE_OLD_MUSIC_FUNCTIONS -#define FROBNICATE_HANDLE(reg) ((reg).segment << 16 | (reg).offset) -#define DEFROBNICATE_HANDLE(handle) (make_reg((handle >> 16) & 0xffff, handle & 0xffff)) -#endif - -#define SOUNDCOMMAND(x) _soundCommands.push_back(new MusicEntryCommand(#x, &SoundCommandParser::x)) - -#ifdef USE_OLD_MUSIC_FUNCTIONS -static void script_set_priority(ResourceManager *resMan, SegManager *segMan, SfxState *state, reg_t obj, int priority) { - int song_nr = readSelectorValue(segMan, obj, SELECTOR(number)); - Resource *song = resMan->findResource(ResourceId(kResourceTypeSound, song_nr), 0); - int flags = readSelectorValue(segMan, obj, SELECTOR(flags)); - - if (priority == -1) { - if (song->data[0] == 0xf0) - priority = song->data[1]; - else - warning("Attempt to unset song priority when there is no built-in value"); - - flags &= ~SCI1_SOUND_FLAG_SCRIPTED_PRI; - } else flags |= SCI1_SOUND_FLAG_SCRIPTED_PRI; - - state->sfx_song_renice(FROBNICATE_HANDLE(obj), priority); - writeSelectorValue(segMan, obj, SELECTOR(flags), flags); -} - -SongIterator *build_iterator(ResourceManager *resMan, int song_nr, SongIteratorType type, songit_id_t id) { - Resource *song = resMan->findResource(ResourceId(kResourceTypeSound, song_nr), 0); - - if (!song) - return NULL; - - return songit_new(song->data, song->size, type, id); -} - -void process_sound_events(EngineState *s) { /* Get all sound events, apply their changes to the heap */ - int result; - SongHandle handle; - int cue; - SegManager *segMan = s->_segMan; - - if (getSciVersion() > SCI_VERSION_01) - return; - // SCI1 and later explicitly poll for everything - - while ((result = s->_sound.sfx_poll(&handle, &cue))) { - reg_t obj = DEFROBNICATE_HANDLE(handle); - if (!s->_segMan->isObject(obj)) { - warning("Non-object %04x:%04x received sound signal (%d/%d)", PRINT_REG(obj), result, cue); - return; - } - - switch (result) { - - case SI_LOOP: - debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x looped (to %d)", - PRINT_REG(obj), cue); - /* writeSelectorValue(segMan, obj, SELECTOR(loops), readSelectorValue(segMan, obj, SELECTOR(loop));; - 1);*/ - writeSelectorValue(segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - break; - - case SI_RELATIVE_CUE: - debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x received relative cue %d", - PRINT_REG(obj), cue); - writeSelectorValue(segMan, obj, SELECTOR(signal), cue + 0x7f); - break; - - case SI_ABSOLUTE_CUE: - debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x received absolute cue %d", - PRINT_REG(obj), cue); - writeSelectorValue(segMan, obj, SELECTOR(signal), cue); - break; - - case SI_FINISHED: - debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x finished", - PRINT_REG(obj)); - writeSelectorValue(segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - writeSelectorValue(segMan, obj, SELECTOR(state), kSoundStopped); - break; - - default: - warning("Unexpected result from sfx_poll: %d", result); - break; - } - } -} - -#endif SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, AudioPlayer *audio, SciVersion soundVersion) : _resMan(resMan), _segMan(segMan), _kernel(kernel), _audio(audio), _soundVersion(soundVersion) { -#ifdef USE_OLD_MUSIC_FUNCTIONS - // The following hack is needed to ease the change from old to new sound code (because the new sound code does not use SfxState) - _state = &g_sci->getEngineState()->_sound; // HACK -#endif - - #ifndef USE_OLD_MUSIC_FUNCTIONS - _music = new SciMusic(_soundVersion); - _music->init(); - #endif - - switch (_soundVersion) { - case SCI_VERSION_0_EARLY: - case SCI_VERSION_0_LATE: - SOUNDCOMMAND(cmdInitSound); - SOUNDCOMMAND(cmdPlaySound); - SOUNDCOMMAND(cmdDummy); - SOUNDCOMMAND(cmdDisposeSound); - SOUNDCOMMAND(cmdMuteSound); - SOUNDCOMMAND(cmdStopSound); - SOUNDCOMMAND(cmdPauseSound); - SOUNDCOMMAND(cmdResumeSound); - SOUNDCOMMAND(cmdMasterVolume); - SOUNDCOMMAND(cmdUpdateSound); - SOUNDCOMMAND(cmdFadeSound); - SOUNDCOMMAND(cmdGetPolyphony); - SOUNDCOMMAND(cmdStopAllSounds); - _cmdUpdateCuesIndex = -1; - break; - case SCI_VERSION_1_EARLY: - SOUNDCOMMAND(cmdMasterVolume); - SOUNDCOMMAND(cmdMuteSound); - SOUNDCOMMAND(cmdDummy); - SOUNDCOMMAND(cmdGetPolyphony); - SOUNDCOMMAND(cmdUpdateSound); - SOUNDCOMMAND(cmdInitSound); - SOUNDCOMMAND(cmdDisposeSound); - SOUNDCOMMAND(cmdPlaySound); - SOUNDCOMMAND(cmdStopSound); - SOUNDCOMMAND(cmdPauseSound); - SOUNDCOMMAND(cmdFadeSound); - SOUNDCOMMAND(cmdUpdateCues); - SOUNDCOMMAND(cmdSendMidi); - SOUNDCOMMAND(cmdReverb); - SOUNDCOMMAND(cmdSetSoundHold); - _cmdUpdateCuesIndex = 11; - break; - case SCI_VERSION_1_LATE: - SOUNDCOMMAND(cmdMasterVolume); - SOUNDCOMMAND(cmdMuteSound); - SOUNDCOMMAND(cmdDummy); - SOUNDCOMMAND(cmdGetPolyphony); - SOUNDCOMMAND(cmdGetAudioCapability); - SOUNDCOMMAND(cmdSuspendSound); - SOUNDCOMMAND(cmdInitSound); - SOUNDCOMMAND(cmdDisposeSound); - SOUNDCOMMAND(cmdPlaySound); - SOUNDCOMMAND(cmdStopSound); - SOUNDCOMMAND(cmdPauseSound); - SOUNDCOMMAND(cmdFadeSound); - SOUNDCOMMAND(cmdSetSoundHold); - SOUNDCOMMAND(cmdDummy); - SOUNDCOMMAND(cmdSetSoundVolume); - SOUNDCOMMAND(cmdSetSoundPriority); - SOUNDCOMMAND(cmdSetSoundLoop); - SOUNDCOMMAND(cmdUpdateCues); - SOUNDCOMMAND(cmdSendMidi); - SOUNDCOMMAND(cmdReverb); - SOUNDCOMMAND(cmdUpdateSound); - _cmdUpdateCuesIndex = 17; - break; - default: - warning("Sound command parser: unknown sound version %d", _soundVersion); - break; - } + _music = new SciMusic(_soundVersion); + _music->init(); } SoundCommandParser::~SoundCommandParser() { - for (SoundCommandContainer::iterator i = _soundCommands.begin(); i != _soundCommands.end(); ++i) - delete *i; - -#ifndef USE_OLD_MUSIC_FUNCTIONS delete _music; -#endif } -reg_t SoundCommandParser::parseCommand(int argc, reg_t *argv, reg_t acc) { - uint16 command = argv[0].toUint16(); - reg_t obj = (argc > 1) ? argv[1] : NULL_REG; - int16 value = (argc > 2) ? argv[2].toSint16() : 0; - _acc = acc; - _argc = argc; - _argv = argv; - - if (argc == 6) { // cmdSendMidi - byte channel = argv[2].toUint16() & 0xf; - byte midiCmd = argv[3].toUint16() & 0xff; - - uint16 controller = argv[4].toUint16(); - uint16 param = argv[5].toUint16(); - - _midiCommand = (channel | midiCmd) | ((uint32)controller << 8) | ((uint32)param << 16); - } - - if (command < _soundCommands.size()) { - if (command != _cmdUpdateCuesIndex) { - //printf("%s, object %04x:%04x\n", _soundCommands[command]->desc, PRINT_REG(obj)); // debug - debugC(2, kDebugLevelSound, "%s, object %04x:%04x", _soundCommands[command]->desc, PRINT_REG(obj)); - } - - (this->*(_soundCommands[command]->sndCmd))(obj, value); - } else { - warning("Invalid sound command requested (%d), valid range is 0-%d", command, _soundCommands.size() - 1); - } - - return _acc; +reg_t SoundCommandParser::kDoSoundInit(int argc, reg_t *argv, reg_t acc) { + processInitSound(argv[0]); + return acc; } -void SoundCommandParser::cmdInitSound(reg_t obj, int16 value) { - if (!obj.segment) - return; - +void SoundCommandParser::processInitSound(reg_t obj) { int resourceId = readSelectorValue(_segMan, obj, SELECTOR(number)); -#ifdef USE_OLD_MUSIC_FUNCTIONS - - SongHandle handle = FROBNICATE_HANDLE(obj); - - if (_soundVersion != SCI_VERSION_1_LATE) { - if (!obj.segment) - return; - } - - SongIteratorType type = (_soundVersion <= SCI_VERSION_0_LATE) ? SCI_SONG_ITERATOR_TYPE_SCI0 : SCI_SONG_ITERATOR_TYPE_SCI1; - - if (_soundVersion <= SCI_VERSION_0_LATE) { - if (readSelectorValue(_segMan, obj, SELECTOR(nodePtr))) { - _state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED); - _state->sfx_remove_song(handle); - } - } - - if (!obj.segment || !_resMan->testResource(ResourceId(kResourceTypeSound, resourceId))) - return; - - _state->sfx_add_song(build_iterator(_resMan, resourceId, type, handle), 0, handle, resourceId); - - - // Notify the engine - if (_soundVersion <= SCI_VERSION_0_LATE) - writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundInitialized); - else - writeSelector(_segMan, obj, SELECTOR(nodePtr), obj); - - writeSelector(_segMan, obj, SELECTOR(handle), obj); - -#else - // Check if a track with the same sound object is already playing MusicEntry *oldSound = _music->getSlot(obj); if (oldSound) - cmdDisposeSound(obj, value); + processDisposeSound(obj); MusicEntry *newSound = new MusicEntry(); newSound->resourceId = resourceId; @@ -307,6 +73,9 @@ void SoundCommandParser::cmdInitSound(reg_t obj, int16 value) { if (_soundVersion >= SCI_VERSION_1_EARLY) newSound->volume = CLIP<int>(readSelectorValue(_segMan, obj, SELECTOR(vol)), 0, MUSIC_VOLUME_MAX); + debugC(2, kDebugLevelSound, "kDoSound(init): number %d, loop %d, prio %d, vol %d", resourceId, + newSound->loop, newSound->priority, newSound->volume); + // In SCI1.1 games, sound effects are started from here. If we can find // a relevant audio resource, play it, otherwise switch to synthesized // effects. If the resource exists, play it using map 65535 (sound @@ -333,98 +102,28 @@ void SoundCommandParser::cmdInitSound(reg_t obj, int16 value) { writeSelector(_segMan, obj, SELECTOR(handle), obj); } -#endif - } -void SoundCommandParser::cmdPlaySound(reg_t obj, int16 value) { - if (!obj.segment) - return; - -#ifdef USE_OLD_MUSIC_FUNCTIONS - SongHandle handle = FROBNICATE_HANDLE(obj); - - if (_soundVersion <= SCI_VERSION_0_LATE) { - _state->sfx_song_set_status(handle, SOUND_STATUS_PLAYING); - _state->sfx_song_set_loops(handle, readSelectorValue(_segMan, obj, SELECTOR(loop))); - writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundPlaying); - } else if (_soundVersion == SCI_VERSION_1_EARLY) { - _state->sfx_song_set_status(handle, SOUND_STATUS_PLAYING); - _state->sfx_song_set_loops(handle, readSelectorValue(_segMan, obj, SELECTOR(loop))); - _state->sfx_song_renice(handle, readSelectorValue(_segMan, obj, SELECTOR(pri))); - RESTORE_BEHAVIOR rb = (RESTORE_BEHAVIOR) value; /* Too lazy to look up a default value for this */ - _state->_songlib.setSongRestoreBehavior(handle, rb); - writeSelectorValue(_segMan, obj, SELECTOR(signal), 0); - } else if (_soundVersion == SCI_VERSION_1_LATE) { - int looping = readSelectorValue(_segMan, obj, SELECTOR(loop)); - //int vol = readSelectorValue(_segMan, obj, SELECTOR(vol)); - int pri = readSelectorValue(_segMan, obj, SELECTOR(pri)); - int sampleLen = 0; - Song *song = _state->_songlib.findSong(handle); - int songNumber = readSelectorValue(_segMan, obj, SELECTOR(number)); - - if (readSelectorValue(_segMan, obj, SELECTOR(nodePtr)) && (song && songNumber != song->_resourceNum)) { - _state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED); - _state->sfx_remove_song(handle); - writeSelector(_segMan, obj, SELECTOR(nodePtr), NULL_REG); - } - - if (!readSelectorValue(_segMan, obj, SELECTOR(nodePtr)) && obj.segment) { - // In SCI1.1 games, sound effects are started from here. If we can find - // a relevant audio resource, play it, otherwise switch to synthesized - // effects. If the resource exists, play it using map 65535 (sound - // effects map) - if (_resMan->testResource(ResourceId(kResourceTypeAudio, songNumber)) && - getSciVersion() >= SCI_VERSION_1_1) { - // Found a relevant audio resource, play it - _audio->stopAudio(); - warning("Initializing audio resource instead of requested sound resource %d", songNumber); - sampleLen = _audio->startAudio(65535, songNumber); - // Also create iterator, that will fire SI_FINISHED event, when the sound is done playing - _state->sfx_add_song(new_timer_iterator(sampleLen), 0, handle, songNumber); - } else { - if (!_resMan->testResource(ResourceId(kResourceTypeSound, songNumber))) { - warning("Could not open song number %d", songNumber); - // Send a "stop handle" event so that the engine won't wait forever here - _state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED); - writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - return; - } - debugC(2, kDebugLevelSound, "Initializing song number %d", songNumber); - _state->sfx_add_song(build_iterator(_resMan, songNumber, SCI_SONG_ITERATOR_TYPE_SCI1, - handle), 0, handle, songNumber); - } - - writeSelector(_segMan, obj, SELECTOR(nodePtr), obj); - writeSelector(_segMan, obj, SELECTOR(handle), obj); - } - - if (obj.segment) { - _state->sfx_song_set_status(handle, SOUND_STATUS_PLAYING); - _state->sfx_song_set_loops(handle, looping); - _state->sfx_song_renice(handle, pri); - writeSelectorValue(_segMan, obj, SELECTOR(signal), 0); - } - } - -#else +reg_t SoundCommandParser::kDoSoundPlay(int argc, reg_t *argv, reg_t acc) { + processPlaySound(argv[0]); + return acc; +} +void SoundCommandParser::processPlaySound(reg_t obj) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdPlaySound: Slot not found (%04x:%04x)", PRINT_REG(obj)); + warning("kDoSound(play): Slot not found (%04x:%04x)", PRINT_REG(obj)); return; } int resourceId = obj.segment ? readSelectorValue(_segMan, obj, SELECTOR(number)) : -1; if (musicSlot->resourceId != resourceId) { // another sound loaded into struct - cmdDisposeSound(obj, value); - cmdInitSound(obj, value); + processDisposeSound(obj); + processInitSound(obj); // Find slot again :) musicSlot = _music->getSlot(obj); } - int16 loop = readSelectorValue(_segMan, obj, SELECTOR(loop)); - debugC(2, kDebugLevelSound, "cmdPlaySound: resource number %d, loop %d", resourceId, loop); writeSelector(_segMan, obj, SELECTOR(handle), obj); @@ -442,51 +141,31 @@ void SoundCommandParser::cmdPlaySound(reg_t obj, int16 value) { musicSlot->priority = readSelectorValue(_segMan, obj, SELECTOR(priority)); if (_soundVersion >= SCI_VERSION_1_EARLY) musicSlot->volume = readSelectorValue(_segMan, obj, SELECTOR(vol)); - _music->soundPlay(musicSlot); -#endif + debugC(2, kDebugLevelSound, "kDoSound(play): number %d, loop %d, prio %d, vol %d", resourceId, + musicSlot->loop, musicSlot->priority, musicSlot->volume); + _music->soundPlay(musicSlot); } -void SoundCommandParser::cmdDummy(reg_t obj, int16 value) { +reg_t SoundCommandParser::kDoSoundDummy(int argc, reg_t *argv, reg_t acc) { warning("cmdDummy invoked"); // not supposed to occur + return acc; } -#ifdef USE_OLD_MUSIC_FUNCTIONS -void SoundCommandParser::changeSoundStatus(reg_t obj, int newStatus) { - SongHandle handle = FROBNICATE_HANDLE(obj); - if (obj.segment) { - _state->sfx_song_set_status(handle, newStatus); - if (_soundVersion <= SCI_VERSION_0_LATE) - writeSelectorValue(_segMan, obj, SELECTOR(state), newStatus); - } +reg_t SoundCommandParser::kDoSoundDispose(int argc, reg_t *argv, reg_t acc) { + processDisposeSound(argv[0]); + return acc; } -#endif - -void SoundCommandParser::cmdDisposeSound(reg_t obj, int16 value) { - if (!obj.segment) - return; - -#ifdef USE_OLD_MUSIC_FUNCTIONS - SongHandle handle = FROBNICATE_HANDLE(obj); - changeSoundStatus(obj, SOUND_STATUS_STOPPED); - - if (obj.segment) { - _state->sfx_remove_song(handle); - - if (_soundVersion <= SCI_VERSION_0_LATE) - writeSelectorValue(_segMan, obj, SELECTOR(handle), 0x0000); - } - -#else +void SoundCommandParser::processDisposeSound(reg_t obj) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdDisposeSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); + warning("kDoSound(dispose): Slot not found (%04x:%04x)", PRINT_REG(obj)); return; } - cmdStopSound(obj, value); + processStopSound(obj, false); _music->soundKill(musicSlot); writeSelectorValue(_segMan, obj, SELECTOR(handle), 0); @@ -494,26 +173,17 @@ void SoundCommandParser::cmdDisposeSound(reg_t obj, int16 value) { writeSelector(_segMan, obj, SELECTOR(nodePtr), NULL_REG); else writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundStopped); -#endif } -void SoundCommandParser::cmdStopSound(reg_t obj, int16 value) { - processStopSound(obj, value, false); +reg_t SoundCommandParser::kDoSoundStop(int argc, reg_t *argv, reg_t acc) { + processStopSound(argv[0], false); + return acc; } -void SoundCommandParser::processStopSound(reg_t obj, int16 value, bool sampleFinishedPlaying) { - if (!obj.segment) - return; - -#ifdef USE_OLD_MUSIC_FUNCTIONS - changeSoundStatus(obj, SOUND_STATUS_STOPPED); - - if (_soundVersion >= SCI_VERSION_1_EARLY) - writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); -#else +void SoundCommandParser::processStopSound(reg_t obj, bool sampleFinishedPlaying) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdStopSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); + warning("kDoSound(stop): Slot not found (%04x:%04x)", PRINT_REG(obj)); return; } @@ -523,204 +193,156 @@ void SoundCommandParser::processStopSound(reg_t obj, int16 value, bool sampleFin writeSelectorValue(_segMan, obj, SELECTOR(handle), 0); } - // Set signal selector in sound SCI0 games only, when the sample has finished playing - // If we don't set it at all, we get a problem when using vaporizer on the 2 guys - // If we set it all the time, we get no music in sq3new and kq1 - // FIXME: this *may* be wrong, it's impossible to find out in sierra DOS sci, because SCI0 under DOS didn't have - // sfx drivers included - // We need to set signal in sound SCI1+ games all the time + // Set signal selector in sound SCI0 games only, when the sample has + // finished playing. If we don't set it at all, we get a problem when using + // vaporizer on the 2 guys. If we set it all the time, we get no music in + // sq3new and kq1. + // FIXME: This *may* be wrong, it's impossible to find out in Sierra DOS + // SCI, because SCI0 under DOS didn't have sfx drivers included. + // We need to set signal in sound SCI1+ games all the time. if ((_soundVersion > SCI_VERSION_0_LATE) || sampleFinishedPlaying) writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); musicSlot->dataInc = 0; musicSlot->signal = 0; _music->soundStop(musicSlot); -#endif } -void SoundCommandParser::cmdPauseSound(reg_t obj, int16 value) { -#ifdef USE_OLD_MUSIC_FUNCTIONS - if (!obj.segment) - return; - - if (_soundVersion <= SCI_VERSION_0_LATE) - changeSoundStatus(obj, SOUND_STATUS_SUSPENDED); - else - changeSoundStatus(obj, value ? SOUND_STATUS_SUSPENDED : SOUND_STATUS_PLAYING); -#else +reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) { + if (_soundVersion <= SCI_VERSION_0_LATE) { + // SCI0 games give us 0/1 for either resuming or pausing the current music + // this one doesn't count, so pausing 2 times and resuming once means here that we are supposed to resume + uint16 value = argv[0].toUint16(); + MusicEntry *musicSlot = _music->getActiveSci0MusicSlot(); + switch (value) { + case 1: + if ((musicSlot) && (musicSlot->status == kSoundPlaying)) { + _music->soundPause(musicSlot); + writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPaused); + } + return make_reg(0, 0); + case 0: + if ((musicSlot) && (musicSlot->status == kSoundPaused)) { + _music->soundResume(musicSlot); + writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPlaying); + return make_reg(0, 1); + } + return make_reg(0, 0); + default: + error("kDoSound(pause): parameter 0 is invalid for sound-sci0"); + } + } + reg_t obj = argv[0]; + uint16 value = argc > 1 ? argv[1].toUint16() : 0; if (!obj.segment) { // pause the whole playlist - // Pausing/Resuming the whole playlist was introduced - // in the SCI1 late sound scheme - if (_soundVersion <= SCI_VERSION_1_EARLY) - return; - _music->pauseAll(value); } else { // pause a playlist slot MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdPauseSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); - return; + warning("kDoSound(pause): Slot not found (%04x:%04x)", PRINT_REG(obj)); + return acc; } - if (_soundVersion <= SCI_VERSION_0_LATE) { - // Always pause the sound in SCI0 games. It's resumed in cmdResumeSound() - writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPaused); - _music->soundPause(musicSlot); - } else { - _music->soundToggle(musicSlot, value); - } + _music->soundToggle(musicSlot, value); } - -#endif + return acc; } -void SoundCommandParser::cmdResumeSound(reg_t obj, int16 value) { - // SCI0 only command - - if (!obj.segment) - return; +// SCI0 only command +reg_t SoundCommandParser::kDoSoundResume(int argc, reg_t *argv, reg_t acc) { + // this doesn't seem to do what we think it's doing + // it's called with no arguments at all (just restore a game in qfg1) + return acc; + reg_t obj = argv[0]; -#ifdef USE_OLD_MUSIC_FUNCTIONS - changeSoundStatus(obj, SOUND_STATUS_PLAYING); -#else MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdResumeSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); - return; + warning("kDoSound(resume):: Slot not found (%04x:%04x)", PRINT_REG(obj)); + return acc; } writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPlaying); _music->soundResume(musicSlot); -#endif + return acc; } -void SoundCommandParser::cmdMuteSound(reg_t obj, int16 value) { -#ifndef USE_OLD_MUSIC_FUNCTIONS - if (_argc > 1) // the first parameter is the sound command - _music->soundSetSoundOn(obj.toUint16()); - _acc = make_reg(0, _music->soundGetSoundOn()); -#endif +reg_t SoundCommandParser::kDoSoundMute(int argc, reg_t *argv, reg_t acc) { + if (argc > 0) + _music->soundSetSoundOn(argv[0].toUint16()); + return make_reg(0, _music->soundGetSoundOn()); } -void SoundCommandParser::cmdMasterVolume(reg_t obj, int16 value) { -#ifdef USE_OLD_MUSIC_FUNCTIONS - _acc = make_reg(0, _state->sfx_getVolume()); - - if (obj != SIGNAL_REG) - _state->sfx_setVolume(obj.toSint16()); -#else - debugC(2, kDebugLevelSound, "cmdMasterVolume: %d", value); - _acc = make_reg(0, _music->soundGetMasterVolume()); +reg_t SoundCommandParser::kDoSoundMasterVolume(int argc, reg_t *argv, reg_t acc) { + acc = make_reg(0, _music->soundGetMasterVolume()); - if (_argc > 1) { // the first parameter is the sound command - int vol = CLIP<int16>(obj.toSint16(), 0, kMaxSciVolume); + if (argc > 0) { + debugC(2, kDebugLevelSound, "kDoSound(masterVolume): %d", argv[0].toSint16()); + int vol = CLIP<int16>(argv[0].toSint16(), 0, kMaxSciVolume); vol = vol * Audio::Mixer::kMaxMixerVolume / kMaxSciVolume; ConfMan.setInt("music_volume", vol); ConfMan.setInt("sfx_volume", vol); g_engine->syncSoundSettings(); } -#endif + return acc; } -void SoundCommandParser::cmdFadeSound(reg_t obj, int16 value) { - if (!obj.segment) - return; +reg_t SoundCommandParser::kDoSoundFade(int argc, reg_t *argv, reg_t acc) { + reg_t obj = argv[0]; -#ifdef USE_OLD_MUSIC_FUNCTIONS - SongHandle handle = FROBNICATE_HANDLE(obj); - if (_soundVersion != SCI_VERSION_1_LATE) { - /* FIXME: The next couple of lines actually STOP the handle, rather - ** than fading it! */ - _state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED); - if (_soundVersion <= SCI_VERSION_0_LATE) - writeSelectorValue(_segMan, obj, SELECTOR(state), SOUND_STATUS_STOPPED); - writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - } else { - fade_params_t fade; - fade.final_volume = _argv[2].toUint16(); - fade.ticks_per_step = _argv[3].toUint16(); - fade.step_size = _argv[4].toUint16(); - fade.action = _argv[5].toUint16() ? - FADE_ACTION_FADE_AND_STOP : - FADE_ACTION_FADE_AND_CONT; - - _state->sfx_song_set_fade(handle, &fade); - - /* FIXME: The next couple of lines actually STOP the handle, rather - ** than fading it! */ - if (_argv[5].toUint16()) { - writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - _state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED); - } else { - // FIXME: Support fade-and-continue. For now, send signal right away. - writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - } - } -#else MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdFadeSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); - return; + warning("kDoSound(fade): Slot not found (%04x:%04x)", PRINT_REG(obj)); + return acc; } int volume = musicSlot->volume; - switch (_argc) { - case 2: // SCI0 - // SCI0 fades out all the time and when fadeout is done it will also stop the music from playing + // If sound is not playing currently, set signal directly + if (musicSlot->status != kSoundPlaying) { + debugC(2, kDebugLevelSound, "kDoSound(fade): fading requested, but sound is currently not playing"); + writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); + return acc; + } + + switch (argc) { + case 1: // SCI0 + // SCI0 fades out all the time and when fadeout is done it will also + // stop the music from playing musicSlot->fadeTo = 0; musicSlot->fadeStep = -5; musicSlot->fadeTickerStep = 10 * 16667 / _music->soundGetTempo(); musicSlot->fadeTicker = 0; break; - case 5: // SCI01+ - case 6: // SCI1+ (SCI1 late sound scheme), with fade and continue - musicSlot->fadeTo = CLIP<uint16>(_argv[2].toUint16(), 0, MUSIC_VOLUME_MAX); - musicSlot->fadeStep = volume > _argv[2].toUint16() ? -_argv[4].toUint16() : _argv[4].toUint16(); - musicSlot->fadeTickerStep = _argv[3].toUint16() * 16667 / _music->soundGetTempo(); + case 4: // SCI01+ + case 5: // SCI1+ (SCI1 late sound scheme), with fade and continue + musicSlot->fadeTo = CLIP<uint16>(argv[1].toUint16(), 0, MUSIC_VOLUME_MAX); + musicSlot->fadeStep = volume > argv[1].toUint16() ? -argv[3].toUint16() : argv[3].toUint16(); + musicSlot->fadeTickerStep = argv[2].toUint16() * 16667 / _music->soundGetTempo(); musicSlot->fadeTicker = 0; - musicSlot->stopAfterFading = (_argc == 6) ? (_argv[5].toUint16() != 0) : false; + musicSlot->stopAfterFading = (argc == 5) ? (argv[4].toUint16() != 0) : false; break; default: - error("cmdFadeSound: unsupported argc %d", _argc); - } - - // If sound is not playing currently, set signal directly - if (musicSlot->status != kSoundPlaying) { - warning("cmdFadeSound: fading requested, but sound is currently not playing"); - writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); + error("kDoSound(fade): unsupported argc %d", argc); } - debugC(2, kDebugLevelSound, "cmdFadeSound: to %d, step %d, ticker %d", musicSlot->fadeTo, musicSlot->fadeStep, musicSlot->fadeTickerStep); -#endif + debugC(2, kDebugLevelSound, "kDoSound(fade): to %d, step %d, ticker %d", musicSlot->fadeTo, musicSlot->fadeStep, musicSlot->fadeTickerStep); + return acc; } -void SoundCommandParser::cmdGetPolyphony(reg_t obj, int16 value) { -#ifdef USE_OLD_MUSIC_FUNCTIONS - _acc = make_reg(0, _state->sfx_get_player_polyphony()); -#else - _acc = make_reg(0, _music->soundGetVoices()); // Get the number of voices -#endif +reg_t SoundCommandParser::kDoSoundGetPolyphony(int argc, reg_t *argv, reg_t acc) { + return make_reg(0, _music->soundGetVoices()); // Get the number of voices } -void SoundCommandParser::cmdUpdateSound(reg_t obj, int16 value) { - if (!obj.segment) - return; +reg_t SoundCommandParser::kDoSoundUpdate(int argc, reg_t *argv, reg_t acc) { + reg_t obj = argv[0]; -#ifdef USE_OLD_MUSIC_FUNCTIONS - SongHandle handle = FROBNICATE_HANDLE(obj); - if (_soundVersion <= SCI_VERSION_0_LATE && obj.segment) { - _state->sfx_song_set_loops(handle, readSelectorValue(_segMan, obj, SELECTOR(loop))); - script_set_priority(_resMan, _segMan, _state, obj, readSelectorValue(_segMan, obj, SELECTOR(pri))); - } -#else MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdUpdateSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); - return; + warning("kDoSound(update): Slot not found (%04x:%04x)", PRINT_REG(obj)); + return acc; } musicSlot->loop = readSelectorValue(_segMan, obj, SELECTOR(loop)); @@ -730,88 +352,18 @@ void SoundCommandParser::cmdUpdateSound(reg_t obj, int16 value) { uint32 objPrio = readSelectorValue(_segMan, obj, SELECTOR(pri)); if (objPrio != musicSlot->priority) _music->soundSetPriority(musicSlot, objPrio); - -#endif + return acc; } -void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) { - if (!obj.segment) - return; - -#ifdef USE_OLD_MUSIC_FUNCTIONS - int signal = 0; - int min = 0; - int sec = 0; - int frame = 0; - int result = SI_LOOP; // small hack - SongHandle handle = FROBNICATE_HANDLE(obj); - - while (result == SI_LOOP) - result = _state->sfx_poll_specific(handle, &signal); - - switch (result) { - case SI_ABSOLUTE_CUE: - debugC(2, kDebugLevelSound, "--- [CUE] %04x:%04x Absolute Cue: %d", - PRINT_REG(obj), signal); - debugC(2, kDebugLevelSound, "abs-signal %04X", signal); - writeSelectorValue(_segMan, obj, SELECTOR(signal), signal); - break; - - case SI_RELATIVE_CUE: - debugC(2, kDebugLevelSound, "--- [CUE] %04x:%04x Relative Cue: %d", - PRINT_REG(obj), signal); - - /* FIXME to match commented-out semantics - * below, with proper storage of dataInc and - * signal in the iterator code. */ - writeSelectorValue(_segMan, obj, SELECTOR(dataInc), signal); - debugC(2, kDebugLevelSound, "rel-signal %04X", signal); - if (_soundVersion == SCI_VERSION_1_EARLY) - writeSelectorValue(_segMan, obj, SELECTOR(signal), signal); - else - writeSelectorValue(_segMan, obj, SELECTOR(signal), signal + 127); - break; - - case SI_FINISHED: - debugC(2, kDebugLevelSound, "--- [FINISHED] %04x:%04x", PRINT_REG(obj)); - writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - break; - - case SI_LOOP: - break; // Doesn't happen - } +reg_t SoundCommandParser::kDoSoundUpdateCues(int argc, reg_t *argv, reg_t acc) { + processUpdateCues(argv[0]); + return acc; +} - //switch (signal) { - //case 0x00: - // if (dataInc != readSelectorValue(segMan, obj, SELECTOR(dataInc))) { - // writeSelectorValue(segMan, obj, SELECTOR(dataInc), dataInc); - // writeSelectorValue(segMan, obj, SELECTOR(signal), dataInc+0x7f); - // } else { - // writeSelectorValue(segMan, obj, SELECTOR(signal), signal); - // } - // break; - //case 0xFF: // May be unnecessary - // s->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED); - // break; - //default : - // if (dataInc != readSelectorValue(segMan, obj, SELECTOR(dataInc))) { - // writeSelectorValue(segMan, obj, SELECTOR(dataInc), dataInc); - // writeSelectorValue(segMan, obj, SELECTOR(signal), dataInc + 0x7f); - // } else { - // writeSelectorValue(segMan, obj, SELECTOR(signal), signal); - // } - // break; - //} - - if (_soundVersion == SCI_VERSION_1_EARLY) { - writeSelectorValue(_segMan, obj, SELECTOR(min), min); - writeSelectorValue(_segMan, obj, SELECTOR(sec), sec); - writeSelectorValue(_segMan, obj, SELECTOR(frame), frame); - } -#else +void SoundCommandParser::processUpdateCues(reg_t obj) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdUpdateCues: Slot not found (%04x:%04x)", PRINT_REG(obj)); + warning("kDoSound(updateCues): Slot not found (%04x:%04x)", PRINT_REG(obj)); return; } @@ -828,7 +380,7 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) { musicSlot->sampleLoopCounter = currentLoopCounter; } if ((!_music->soundIsActive(musicSlot)) && (musicSlot->status != kSoundPaused)) { - processStopSound(obj, 0, true); + processStopSound(obj, true); } else { _music->updateAudioStreamTicker(musicSlot); } @@ -841,7 +393,7 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) { // Update MIDI slots if (musicSlot->signal == 0) { if (musicSlot->dataInc != readSelectorValue(_segMan, obj, SELECTOR(dataInc))) { - if (_kernel->_selectorCache.dataInc > -1) + if (SELECTOR(dataInc) > -1) writeSelectorValue(_segMan, obj, SELECTOR(dataInc), musicSlot->dataInc); writeSelectorValue(_segMan, obj, SELECTOR(signal), musicSlot->dataInc + 127); } @@ -850,13 +402,15 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) { writeSelectorValue(_segMan, obj, SELECTOR(signal), musicSlot->signal); // We need to do this especially because state selector needs to get updated if (musicSlot->signal == SIGNAL_OFFSET) - cmdStopSound(obj, 0); + processStopSound(obj, false); } } else { - // Slot actually has no data (which would mean that a sound-resource w/ unsupported data is used + // Slot actually has no data (which would mean that a sound-resource w/ + // unsupported data is used. // (example lsl5 - sound resource 744 - it's roland exclusive writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - // If we don't set signal here, at least the switch to the mud wrestling room in lsl5 will not work + // If we don't set signal here, at least the switch to the mud wrestling + // room in lsl5 will not work. } if (musicSlot->fadeCompleted) { @@ -864,10 +418,10 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) { // We need signal for sci0 at least in iceman as well (room 14, fireworks) writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); if (_soundVersion <= SCI_VERSION_0_LATE) { - cmdStopSound(obj, 0); + processStopSound(obj, false); } else { if (musicSlot->stopAfterFading) - cmdStopSound(obj, 0); + processStopSound(obj, false); } } @@ -882,48 +436,58 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) { writeSelectorValue(_segMan, obj, SELECTOR(sec), musicSlot->ticker % 3600 / 60); writeSelectorValue(_segMan, obj, SELECTOR(frame), musicSlot->ticker); } - -#endif } -void SoundCommandParser::cmdSendMidi(reg_t obj, int16 value) { -#ifdef USE_OLD_MUSIC_FUNCTIONS - //SongHandle handle = FROBNICATE_HANDLE(obj); - //_state->sfx_send_midi(handle, value, _midiCmd, _controller, _param); -#else - _music->sendMidiCommand(_midiCommand); -#endif +reg_t SoundCommandParser::kDoSoundSendMidi(int argc, reg_t *argv, reg_t acc) { + reg_t obj = argv[0]; + byte channel = argv[1].toUint16() & 0xf; + byte midiCmd = argv[2].toUint16() & 0xff; + + uint16 controller = argv[3].toUint16(); + uint16 param = argv[4].toUint16(); + + if (channel) + channel--; // channel is given 1-based, we are using 0-based + + uint32 midiCommand = (channel | midiCmd) | ((uint32)controller << 8) | ((uint32)param << 16); + + MusicEntry *musicSlot = _music->getSlot(obj); + if (!musicSlot) { + // TODO: maybe it's possible to call this with obj == 0:0 and send directly?! + // if so, allow it + //_music->sendMidiCommand(_midiCommand); + warning("kDoSound(sendMidi): Slot not found (%04x:%04x)", PRINT_REG(obj)); + return acc; + } + _music->sendMidiCommand(musicSlot, midiCommand); + return acc; } -void SoundCommandParser::cmdReverb(reg_t obj, int16 value) { -#ifndef USE_OLD_MUSIC_FUNCTIONS - _music->setReverb(obj.toUint16() & 0xF); -#endif +reg_t SoundCommandParser::kDoSoundReverb(int argc, reg_t *argv, reg_t acc) { + _music->setReverb(argv[0].toUint16() & 0xF); + return acc; } -void SoundCommandParser::cmdSetSoundHold(reg_t obj, int16 value) { -#ifdef USE_OLD_MUSIC_FUNCTIONS - SongHandle handle = FROBNICATE_HANDLE(obj); - _state->sfx_song_set_hold(handle, value); -#else +reg_t SoundCommandParser::kDoSoundSetHold(int argc, reg_t *argv, reg_t acc) { + reg_t obj = argv[0]; + MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdSetSoundHold: Slot not found (%04x:%04x)", PRINT_REG(obj)); - return; + warning("kDoSound(setHold): Slot not found (%04x:%04x)", PRINT_REG(obj)); + return acc; } // Set the special hold marker ID where the song should be looped at. - musicSlot->hold = value; -#endif + musicSlot->hold = argv[1].toSint16(); + return acc; } -void SoundCommandParser::cmdGetAudioCapability(reg_t obj, int16 value) { +reg_t SoundCommandParser::kDoSoundGetAudioCapability(int argc, reg_t *argv, reg_t acc) { // Tests for digital audio support - _acc = make_reg(0, 1); + return make_reg(0, 1); } -void SoundCommandParser::cmdStopAllSounds(reg_t obj, int16 value) { -#ifndef USE_OLD_MUSIC_FUNCTIONS +reg_t SoundCommandParser::kDoSoundStopAll(int argc, reg_t *argv, reg_t acc) { Common::StackLock(_music->_mutex); const MusicList::iterator end = _music->getPlayListEnd(); @@ -931,32 +495,31 @@ void SoundCommandParser::cmdStopAllSounds(reg_t obj, int16 value) { if (_soundVersion <= SCI_VERSION_0_LATE) { writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(state), kSoundStopped); } else { - writeSelectorValue(_segMan, obj, SELECTOR(handle), 0); + writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(handle), 0); writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(signal), SIGNAL_OFFSET); } (*i)->dataInc = 0; _music->soundStop(*i); } -#endif + return acc; } -void SoundCommandParser::cmdSetSoundVolume(reg_t obj, int16 value) { - if (!obj.segment) - return; +reg_t SoundCommandParser::kDoSoundSetVolume(int argc, reg_t *argv, reg_t acc) { + reg_t obj = argv[0]; + int16 value = argv[1].toSint16(); -#ifndef USE_OLD_MUSIC_FUNCTIONS MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { // Do not throw a warning if the sound can't be found, as in some games - // this is called before the actual sound is loaded (e.g. SQ4CD, with the - // drum sounds of the energizer bunny at the beginning), so this is normal - // behavior + // this is called before the actual sound is loaded (e.g. SQ4CD, with + // the drum sounds of the energizer bunny at the beginning), so this is + // normal behavior. //warning("cmdSetSoundVolume: Slot not found (%04x:%04x)", PRINT_REG(obj)); - return; + return acc; } - debugC(2, kDebugLevelSound, "cmdSetSoundVolume: %d", value); + debugC(2, kDebugLevelSound, "kDoSound(setVolume): %d", value); value = CLIP<int>(value, 0, MUSIC_VOLUME_MAX); @@ -965,20 +528,17 @@ void SoundCommandParser::cmdSetSoundVolume(reg_t obj, int16 value) { _music->soundSetVolume(musicSlot, value); writeSelectorValue(_segMan, obj, SELECTOR(vol), value); } -#endif + return acc; } -void SoundCommandParser::cmdSetSoundPriority(reg_t obj, int16 value) { - if (!obj.segment) - return; +reg_t SoundCommandParser::kDoSoundSetPriority(int argc, reg_t *argv, reg_t acc) { + reg_t obj = argv[0]; + int16 value = argv[1].toSint16(); -#ifdef USE_OLD_MUSIC_FUNCTIONS - script_set_priority(_resMan, _segMan, _state, obj, value); -#else MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdSetSoundPriority: Slot not found (%04x:%04x)", PRINT_REG(obj)); - return; + warning("kDoSound(setPriority): Slot not found (%04x:%04x)", PRINT_REG(obj)); + return acc; } if (value == -1) { @@ -987,7 +547,7 @@ void SoundCommandParser::cmdSetSoundPriority(reg_t obj, int16 value) { if (song->data[0] == 0xf0) _music->soundSetPriority(musicSlot, song->data[1]); else - warning("cmdSetSoundPriority: Attempt to unset song priority when there is no built-in value"); + warning("kDoSound(setPriority): Attempt to unset song priority when there is no built-in value"); //pSnd->prio=0;field_15B=0 writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) & 0xFD); @@ -998,32 +558,26 @@ void SoundCommandParser::cmdSetSoundPriority(reg_t obj, int16 value) { writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) | 2); //DoSOund(0xF,hobj,w) } -#endif + return acc; } -void SoundCommandParser::cmdSetSoundLoop(reg_t obj, int16 value) { - if (!obj.segment) - return; +reg_t SoundCommandParser::kDoSoundSetLoop(int argc, reg_t *argv, reg_t acc) { + reg_t obj = argv[0]; + int16 value = argv[1].toSint16(); -#ifdef USE_OLD_MUSIC_FUNCTIONS - if (!readSelector(_segMan, obj, SELECTOR(nodePtr)).isNull()) { - SongHandle handle = FROBNICATE_HANDLE(obj); - _state->sfx_song_set_loops(handle, value); - } -#else MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { // Apparently, it's perfectly normal for a game to call cmdSetSoundLoop // before actually initializing the sound and adding it to the playlist // with cmdInitSound. Usually, it doesn't matter if the game doesn't // request to loop the sound, so in this case, don't throw any warning, - // otherwise do, because the sound won't be looped + // otherwise do, because the sound won't be looped. if (value == -1) { - warning("cmdSetSoundLoop: Slot not found (%04x:%04x) and the song was requested to be looped", PRINT_REG(obj)); + warning("kDoSound(setLoop): Slot not found (%04x:%04x) and the song was requested to be looped", PRINT_REG(obj)); } else { // Doesn't really matter } - return; + return acc; } if (value == -1) { musicSlot->loop = 0xFFFF; @@ -1032,40 +586,37 @@ void SoundCommandParser::cmdSetSoundLoop(reg_t obj, int16 value) { } writeSelectorValue(_segMan, obj, SELECTOR(loop), musicSlot->loop); -#endif + return acc; } -void SoundCommandParser::cmdSuspendSound(reg_t obj, int16 value) { +reg_t SoundCommandParser::kDoSoundSuspend(int argc, reg_t *argv, reg_t acc) { // TODO - warning("STUB: cmdSuspendSound"); + warning("kDoSound(suspend): STUB"); + return acc; } -#ifndef USE_OLD_MUSIC_FUNCTIONS - void SoundCommandParser::updateSci0Cues() { bool noOnePlaying = true; MusicEntry *pWaitingForPlay = NULL; - _music->_mutex.lock(); - const MusicList::iterator end = _music->getPlayListEnd(); for (MusicList::iterator i = _music->getPlayListStart(); i != end; ++i) { // Is the sound stopped, and the sound object updated too? If yes, skip - // this sound, as SCI0 only allows one active song + // this sound, as SCI0 only allows one active song. if ((*i)->isQueued) { pWaitingForPlay = (*i); - // FIXME (?) - in iceman 2 songs are queued when playing the door sound - if we use the first song for resuming - // then it's the wrong one. Both songs have same priority. Maybe the new sound function in sci0 - // is somehow responsible + // FIXME(?): In iceman 2 songs are queued when playing the door + // sound - if we use the first song for resuming then it's the wrong + // one. Both songs have same priority. Maybe the new sound function + // in sci0 is somehow responsible. continue; } if ((*i)->signal == 0 && (*i)->status != kSoundPlaying) continue; - cmdUpdateCues((*i)->soundObj, 0); + processUpdateCues((*i)->soundObj); noOnePlaying = false; } - _music->_mutex.unlock(); if (noOnePlaying && pWaitingForPlay) { // If there is a queued entry, play it now ffs: SciMusic::soundPlay() @@ -1074,90 +625,40 @@ void SoundCommandParser::updateSci0Cues() { } } -#endif - void SoundCommandParser::clearPlayList() { -#ifndef USE_OLD_MUSIC_FUNCTIONS _music->clearPlayList(); -#endif -} - -void SoundCommandParser::syncPlayList(Common::Serializer &s) { -#ifndef USE_OLD_MUSIC_FUNCTIONS - _music->saveLoadWithSerializer(s); -#endif -} - -void SoundCommandParser::reconstructPlayList(int savegame_version) { -#ifndef USE_OLD_MUSIC_FUNCTIONS - Common::StackLock lock(_music->_mutex); - - const MusicList::iterator end = _music->getPlayListEnd(); - for (MusicList::iterator i = _music->getPlayListStart(); i != end; ++i) { - if ((*i)->resourceId && _resMan->testResource(ResourceId(kResourceTypeSound, (*i)->resourceId))) { - (*i)->soundRes = new SoundResource((*i)->resourceId, _resMan, _soundVersion); - _music->soundInitSnd(*i); - } else { - (*i)->soundRes = 0; - } - if ((*i)->status == kSoundPlaying) { - if (savegame_version < 14) { - (*i)->dataInc = readSelectorValue(_segMan, (*i)->soundObj, SELECTOR(dataInc)); - (*i)->signal = readSelectorValue(_segMan, (*i)->soundObj, SELECTOR(signal)); - - if (_soundVersion >= SCI_VERSION_1_LATE) - (*i)->volume = readSelectorValue(_segMan, (*i)->soundObj, SELECTOR(vol)); - } - - cmdPlaySound((*i)->soundObj, 0); - } - } - -#endif } void SoundCommandParser::printPlayList(Console *con) { -#ifndef USE_OLD_MUSIC_FUNCTIONS _music->printPlayList(con); -#endif } void SoundCommandParser::printSongInfo(reg_t obj, Console *con) { -#ifndef USE_OLD_MUSIC_FUNCTIONS _music->printSongInfo(obj, con); -#endif } void SoundCommandParser::stopAllSounds() { -#ifndef USE_OLD_MUSIC_FUNCTIONS _music->stopAll(); -#endif } void SoundCommandParser::startNewSound(int number) { -#ifndef USE_OLD_MUSIC_FUNCTIONS Common::StackLock lock(_music->_mutex); // Overwrite the first sound in the playlist MusicEntry *song = *_music->getPlayListStart(); reg_t soundObj = song->soundObj; - cmdDisposeSound(soundObj, 0); + processDisposeSound(soundObj); writeSelectorValue(_segMan, soundObj, SELECTOR(number), number); - cmdInitSound(soundObj, 0); - cmdPlaySound(soundObj, 0); -#endif + processInitSound(soundObj); + processPlaySound(soundObj); } void SoundCommandParser::setMasterVolume(int vol) { -#ifndef USE_OLD_MUSIC_FUNCTIONS _music->soundSetMasterVolume(vol); -#endif } void SoundCommandParser::pauseAll(bool pause) { -#ifndef USE_OLD_MUSIC_FUNCTIONS _music->pauseAll(pause); -#endif } } // End of namespace Sci diff --git a/engines/sci/sound/soundcmd.h b/engines/sci/sound/soundcmd.h index 09cca23450..a8bc1eb280 100644 --- a/engines/sci/sound/soundcmd.h +++ b/engines/sci/sound/soundcmd.h @@ -26,8 +26,6 @@ #ifndef SCI_SOUNDCMD_H #define SCI_SOUNDCMD_H -#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS - #include "common/list.h" #include "sci/engine/state.h" @@ -36,13 +34,13 @@ namespace Sci { class Console; class SciMusic; class SoundCommandParser; -typedef void (SoundCommandParser::*SoundCommand)(reg_t obj, int16 value); +//typedef void (SoundCommandParser::*SoundCommand)(reg_t obj, int16 value); -struct MusicEntryCommand { - MusicEntryCommand(const char *d, SoundCommand c) : sndCmd(c), desc(d) {} - SoundCommand sndCmd; - const char *desc; -}; +//struct MusicEntryCommand { +// MusicEntryCommand(const char *d, SoundCommand c) : sndCmd(c), desc(d) {} +// SoundCommand sndCmd; +// const char *desc; +//}; class SoundCommandParser { public: @@ -53,11 +51,7 @@ public: kMaxSciVolume = 15 }; -#ifdef USE_OLD_MUSIC_FUNCTIONS - void updateSfxState(SfxState *newState) { _state = newState; } -#endif - - reg_t parseCommand(int argc, reg_t *argv, reg_t acc); + //reg_t parseCommand(int argc, reg_t *argv, reg_t acc); // Functions used for game state loading void clearPlayList(); @@ -69,14 +63,14 @@ public: void pauseAll(bool pause); // Debug console functions - void playSound(reg_t obj) { cmdPlaySound(obj, 0); } - void stopSound(reg_t obj) { cmdStopSound(obj, 0); } void startNewSound(int number); void stopAllSounds(); void printPlayList(Console *con); void printSongInfo(reg_t obj, Console *con); -#ifndef USE_OLD_MUSIC_FUNCTIONS + void processPlaySound(reg_t obj); + void processStopSound(reg_t obj, bool sampleFinishedPlaying); + /** * Synchronizes the current state of the music list to the rest of the engine, so that * the changes that the sound thread makes to the music are registered with the engine @@ -85,56 +79,43 @@ public: * by the engine scripts themselves, so the engine itself polls for changes to the music */ void updateSci0Cues(); -#endif + + reg_t kDoSoundInit(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundPlay(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundDummy(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundMute(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundPause(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundResume(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundStop(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundStopAll(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundDispose(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundMasterVolume(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundFade(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundGetPolyphony(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundUpdate(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundUpdateCues(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundSendMidi(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundReverb(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundSetHold(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundGetAudioCapability(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundSetVolume(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundSetPriority(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundSetLoop(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundSuspend(int argc, reg_t *argv, reg_t acc); private: - typedef Common::Array<MusicEntryCommand *> SoundCommandContainer; - SoundCommandContainer _soundCommands; + //typedef Common::Array<MusicEntryCommand *> SoundCommandContainer; + //SoundCommandContainer _soundCommands; ResourceManager *_resMan; SegManager *_segMan; Kernel *_kernel; -#ifdef USE_OLD_MUSIC_FUNCTIONS - SfxState *_state; - int _midiCmd, _controller, _param; -#else SciMusic *_music; -#endif AudioPlayer *_audio; SciVersion _soundVersion; - int _argc; - reg_t *_argv; // for cmdFadeSound - uint32 _midiCommand; // for cmdSendMidi - reg_t _acc; - int _cmdUpdateCuesIndex; - - void cmdInitSound(reg_t obj, int16 value); - void cmdPlaySound(reg_t obj, int16 value); - void cmdDummy(reg_t obj, int16 value); - void cmdMuteSound(reg_t obj, int16 value); - void cmdPauseSound(reg_t obj, int16 value); - void cmdResumeSound(reg_t obj, int16 value); - void cmdStopSound(reg_t obj, int16 value); - void cmdDisposeSound(reg_t obj, int16 value); - void cmdMasterVolume(reg_t obj, int16 value); - void cmdFadeSound(reg_t obj, int16 value); - void cmdGetPolyphony(reg_t obj, int16 value); - void cmdStopAllSounds(reg_t obj, int16 value); - void cmdUpdateSound(reg_t obj, int16 value); - void cmdUpdateCues(reg_t obj, int16 value); - void cmdSendMidi(reg_t obj, int16 value); - void cmdReverb(reg_t obj, int16 value); - void cmdSetSoundHold(reg_t obj, int16 value); - void cmdGetAudioCapability(reg_t obj, int16 value); - void cmdSetSoundVolume(reg_t obj, int16 value); - void cmdSetSoundPriority(reg_t obj, int16 value); - void cmdSetSoundLoop(reg_t obj, int16 value); - void cmdSuspendSound(reg_t obj, int16 value); - - void processStopSound(reg_t obj, int16 value, bool sampleFinishedPlaying); - -#ifdef USE_OLD_MUSIC_FUNCTIONS - void changeSoundStatus(reg_t obj, int newStatus); -#endif + + void processInitSound(reg_t obj); + void processDisposeSound(reg_t obj); + void processUpdateCues(reg_t obj); }; } // End of namespace Sci diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp index 0e0c0e129e..fa4804ce7d 100644 --- a/engines/scumm/charset.cpp +++ b/engines/scumm/charset.cpp @@ -109,10 +109,9 @@ void ScummEngine::loadCJKFont() { numChar = 8192; break; case Common::ZH_TWN: - if (_game.id == GID_CMI) { - fontFile = "chinese.fnt"; - numChar = 13630; - } + // Both The DIG and COMI use same font + fontFile = "chinese.fnt"; + numChar = 13630; break; case Common::ZH_CNA: if (_game.id == GID_FT || _game.id == GID_LOOM || _game.id == GID_INDY3 || diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 7275caaa1e..9721c75677 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -314,7 +314,7 @@ static Common::Language detectLanguage(const Common::FSList &fslist, byte id) { case 449787: // 64f3fe479d45b52902cf88145c41d172 return Common::ES_ESP; } - } else { + } else { // The DIG switch (size) { case 248627: // 1fd585ac849d57305878c77b2f6c74ff return Common::DE_DEU; @@ -328,6 +328,8 @@ static Common::Language detectLanguage(const Common::FSList &fslist, byte id) { return Common::ES_ESP; case 223107: // 64f3fe479d45b52902cf88145c41d172 return Common::JA_JPN; + case 180730: // 424fdd60822722cdc75356d921dad9bf + return Common::ZH_TWN; } } } @@ -381,10 +383,12 @@ static void computeGameSettingsFromMD5(const Common::FSList &fslist, const GameF } } -static void detectGames(const Common::FSList &fslist, Common::List<DetectorResult> &results, const char *gameid) { - DescMap fileMD5Map; - DetectorResult dr; - char md5str[32+1]; +static void composeFileHashMap(const Common::FSList &fslist, DescMap &fileMD5Map, int depth, const char **globs) { + if (depth <= 0) + return; + + if (fslist.empty()) + return; for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { if (!file->isDirectory()) { @@ -392,8 +396,36 @@ static void detectGames(const Common::FSList &fslist, Common::List<DetectorResul d.node = *file; d.md5Entry = 0; fileMD5Map[file->getName()] = d; + } else { + if (!globs) + continue; + + bool matched = false; + for (const char *glob = *globs; *glob; glob++) + if (file->getName().matchString(glob, true)) { + matched = true; + break; + } + + if (!matched) + continue; + + Common::FSList files; + + if (file->getChildren(files, Common::FSNode::kListAll)) { + composeFileHashMap(files, fileMD5Map, depth - 1, globs); + } } } +} + +static void detectGames(const Common::FSList &fslist, Common::List<DetectorResult> &results, const char *gameid) { + DescMap fileMD5Map; + DetectorResult dr; + char md5str[32+1]; + + // Dive one level down since mac indy3/loom has its files split into directories. See Bug #1438631 + composeFileHashMap(fslist, fileMD5Map, 2, directoryGlobs); // Iterate over all filename patterns. for (const GameFilenamePattern *gfp = gameFilenamesTable; gfp->gameid; ++gfp) { @@ -458,6 +490,12 @@ static void detectGames(const Common::FSList &fslist, Common::List<DetectorResul // Exact match found. Compute the precise game settings. computeGameSettingsFromMD5(fslist, gfp, d.md5Entry, dr); + // Print some debug info + int filesize = tmp->size(); + if (d.md5Entry->filesize != filesize) + debug(1, "SCUMM detector found matching file '%s' with MD5 %s, size %d\n", + file.c_str(), md5str, filesize); + // Sanity check: We *should* have found a matching gameid / variant at this point. // If not, then there's a bug in our data tables... assert(dr.game.gameid != 0); @@ -866,7 +904,8 @@ GameList ScummMetaEngine::detectGames(const Common::FSList &fslist) const { } } - dg.setGUIOptions(x->game.guioptions); + dg.setGUIOptions(x->game.guioptions | MidiDriver::musicType2GUIO(x->game.midi)); + dg.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(x->language)); detectedGames.push_back(dg); } @@ -966,6 +1005,10 @@ Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) co debug(1, "Using MD5 '%s'", res.md5.c_str()); } + // If the GUI options were updated, we catch this here and update them in the users config + // file transparently. + Common::updateGameGUIOptions(res.game.guioptions, getGameGUIOptionsDescriptionLanguage(res.language)); + // Check for a user override of the platform. We allow the user to override // the platform, to make it possible to add games which are not yet in // our MD5 database but require a specific platform setting. @@ -982,11 +1025,6 @@ Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) co // TODO: Maybe allow the null driver, too? if (res.game.platform == Common::kPlatformFMTowns && res.game.version == 3) res.game.midi = MDT_TOWNS; - - // If the GUI options were updated, we catch this here and update them in the users config - // file transparently. - Common::updateGameGUIOptions(res.game.guioptions); - // Finally, we have massaged the GameDescriptor to our satisfaction, and can // instantiate the appropriate game engine. Hooray! switch (res.game.version) { diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index 0b90af4ec4..d8987c816f 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -48,6 +48,15 @@ namespace Scumm { #pragma mark --- Tables --- #pragma mark - +/** + * This table contains list of directories which could contain game data + * and which should be looked into during detection. + */ +static const char *directoryGlobs[] = { + "rooms *", // Mac version of indy3/loom + 0 +}; + /** * This table contains all game IDs supported by the SCUMM engine, and maps @@ -215,7 +224,7 @@ static const GameSettings gameVariantsTable[] = { {"indy3", "VGA", "vga", GID_INDY3, 3, 0, MDT_PCSPK | MDT_ADLIB, GF_OLD256 | GF_FEW_LOCALS, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI}, {"indy3", "FM-TOWNS", 0, GID_INDY3, 3, 0, MDT_TOWNS, GF_OLD256 | GF_FEW_LOCALS | GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_NOMIDI}, - {"loom", "EGA", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH}, + {"loom", "EGA", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH}, {"loom", "No AdLib", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_CMS, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI}, #ifdef USE_RGB_COLOR {"loom", "PC-Engine", 0, GID_LOOM, 3, 0, MDT_NONE, GF_AUDIOTRACKS | GF_OLD256 | GF_16BIT_COLOR, Common::kPlatformPCEngine, GUIO_NOSPEECH | GUIO_NOMIDI}, @@ -225,24 +234,24 @@ static const GameSettings gameVariantsTable[] = { {"pass", 0, 0, GID_PASS, 4, 0, MDT_PCSPK | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI}, - {"monkey", "VGA", "vga", GID_MONKEY_VGA, 4, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH}, - {"monkey", "EGA", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH}, + {"monkey", "VGA", "vga", GID_MONKEY_VGA, 4, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH}, + {"monkey", "EGA", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH}, {"monkey", "No AdLib", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK, GF_16COLOR, Common::kPlatformAtariST, GUIO_NOSPEECH | GUIO_NOMIDI}, {"monkey", "Demo", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI}, {"monkey", "CD", 0, GID_MONKEY, 5, 0, MDT_ADLIB, GF_AUDIOTRACKS, UNK, GUIO_NOSPEECH | GUIO_NOMIDI}, {"monkey", "FM-TOWNS", 0, GID_MONKEY, 5, 0, MDT_ADLIB, GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_NOMIDI}, {"monkey", "SEGA", 0, GID_MONKEY, 5, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformSegaCD, GUIO_NOSPEECH | GUIO_NOMIDI}, - {"monkey2", 0, 0, GID_MONKEY2, 5, 0, MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH}, + {"monkey2", 0, 0, GID_MONKEY2, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH}, - {"atlantis", "" , 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NONE}, - {"atlantis", "Floppy", 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH}, + {"atlantis", "" , 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NONE}, + {"atlantis", "Floppy", 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH}, - {"tentacle", "", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE}, - {"tentacle", "Floppy", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NOSPEECH}, + {"tentacle", "", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NONE}, + {"tentacle", "Floppy", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NOSPEECH}, - {"samnmax", "", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE}, - {"samnmax", "Floppy", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NOSPEECH}, + {"samnmax", "", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NONE}, + {"samnmax", "Floppy", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NOSPEECH}, #ifdef ENABLE_SCUMM_7_8 {"ft", 0, 0, GID_FT, 7, 0, MDT_NONE, 0, UNK, GUIO_NOMIDI}, diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp index d9c24ddca2..1e0bf6d4be 100644 --- a/engines/scumm/dialogs.cpp +++ b/engines/scumm/dialogs.cpp @@ -26,6 +26,7 @@ #include "common/savefile.h" #include "common/system.h" #include "common/events.h" +#include "common/translation.h" #include "graphics/scaler.h" @@ -283,9 +284,9 @@ HelpDialog::HelpDialog(const GameSettings &game) _numPages = ScummHelp::numPages(_game.id); - _prevButton = new GUI::ButtonWidget(this, "ScummHelp.Prev", "Previous", kPrevCmd, 'P'); - _nextButton = new GUI::ButtonWidget(this, "ScummHelp.Next", "Next", kNextCmd, 'N'); - new GUI::ButtonWidget(this, "ScummHelp.Close", "Close", GUI::kCloseCmd, 'C'); + _prevButton = new GUI::ButtonWidget(this, "ScummHelp.Prev", _("~P~revious"), 0, kPrevCmd); + _nextButton = new GUI::ButtonWidget(this, "ScummHelp.Next", _("~N~ext"), 0, kNextCmd); + new GUI::ButtonWidget(this, "ScummHelp.Close", _("~C~lose"), 0, GUI::kCloseCmd); _prevButton->clearFlags(WIDGET_ENABLED); _numLines = HELP_NUM_LINES; diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp index 1375281aaf..1d064cdf6a 100644 --- a/engines/scumm/saveload.cpp +++ b/engines/scumm/saveload.cpp @@ -576,6 +576,10 @@ bool ScummEngine::loadState(int slot, bool compat) { // Fixes bug #1766072: MANIACNES: Music Doesn't Start On Load Game if (_game.platform == Common::kPlatformNES) { runScript(5, 0, 0, 0); + + if (VAR(224)) { + _sound->addSoundToQueue(VAR(224)); + } } return true; diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp index b1545db0f3..5c20e0dfd3 100644 --- a/engines/scumm/script_v5.cpp +++ b/engines/scumm/script_v5.cpp @@ -2594,6 +2594,17 @@ void ScummEngine_v5::decodeParseString() { else strcpy((char *)tmpBuf+16, "^19^"); printString(textSlot, tmpBuf); + } else if (_game.id == GID_MONKEY_EGA && _roomResource == 30 && vm.slot[_currentScript].number == 411 && + strstr((const char *)_scriptPointer, "NCREDIT-NOTE-AMOUNT")) { + // WORKAROUND for bug #3003643 (MI1EGA German: Credit text incorrect) + // The script contains buggy text. + const char *tmp = strstr((const char *)_scriptPointer, "NCREDIT-NOTE-AMOUNT"); + char tmpBuf[256]; + const int diff = tmp - (const char *)_scriptPointer; + memcpy(tmpBuf, _scriptPointer, diff); + strcpy(tmpBuf + diff, "5000"); + strcpy(tmpBuf + diff + 4, tmp + sizeof("NCREDIT-NOTE-AMOUNT") - 1); + printString(textSlot, (byte *)tmpBuf); } else { printString(textSlot, _scriptPointer); } diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h index cc382d9621..a25fac1a88 100644 --- a/engines/scumm/scumm-md5.h +++ b/engines/scumm/scumm-md5.h @@ -1,5 +1,5 @@ /* - This file was generated by the md5table tool on Mon May 24 13:24:24 2010 + This file was generated by the md5table tool on Sun Jun 27 05:23:26 2010 DO NOT EDIT MANUALLY! */ @@ -40,14 +40,14 @@ static const MD5Table md5table[] = { { "0a295b80f9a9edf818e8e161a0e83830", "freddi2", "HE 80", "", -1, Common::FR_FRA, Common::kPlatformUnknown }, { "0a41311d462b6639fc45297b9044bf16", "monkey", "No AdLib", "EGA", -1, Common::ES_ESP, Common::kPlatformAtariST }, { "0a6d7b81b850ed4a77811c60c9b5c555", "PuttTime", "HE 99", "Mini Game", -1, Common::EN_USA, Common::kPlatformWindows }, - { "0aa050f4ad79402fbe9c4f78fb8ac494", "loom", "PC-Engine", "", -1, Common::EN_ANY, Common::kPlatformPCEngine }, + { "0aa050f4ad79402fbe9c4f78fb8ac494", "loom", "PC-Engine", "", 6532, Common::EN_ANY, Common::kPlatformPCEngine }, { "0ab19be9e2a3f6938226638b2a3744fe", "PuttTime", "HE 100", "Demo", -1, Common::EN_USA, Common::kPlatformUnknown }, { "0ac41e2e3d2174e5a042a6b565328dba", "puttrace", "HE 98", "Demo", 13110, Common::EN_USA, Common::kPlatformUnknown }, { "0b3222aaa7efcf283eb621e0cefd26cc", "puttputt", "HE 60", "", -1, Common::RU_RUS, Common::kPlatformPC }, { "0be88565f734b1e9e77ccaaf3bb14b29", "loom", "EGA", "EGA", -1, Common::ES_ESP, Common::kPlatformPC }, { "0bf1a3eb198ca1bd2ebe104825cec770", "puttrace", "HE 99", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows }, { "0c331637580950aea2346e012ef2a868", "maniac", "V2", "V2", 1988, Common::EN_ANY, Common::kPlatformAtariST }, - { "0c45eb4baff0c12c3d9dfa889c8070ab", "pajama3", "", "Demo", -1, Common::DE_DEU, Common::kPlatformUnknown }, + { "0c45eb4baff0c12c3d9dfa889c8070ab", "pajama3", "", "Demo", 13884, Common::DE_DEU, Common::kPlatformUnknown }, { "0cccfa5223099a60e76cfcca57a1a141", "freddi3", "", "", -1, Common::NL_NLD, Common::kPlatformUnknown }, { "0d1b69471605201ef2fa9cec1f5f02d2", "maniac", "V2", "V2", -1, Common::ES_ESP, Common::kPlatformPC }, { "0e4c5d54a0ad4b26132e78b5ea76642a", "samnmax", "Floppy", "Demo", 6485, Common::EN_ANY, Common::kPlatformPC }, @@ -75,11 +75,11 @@ static const MD5Table md5table[] = { { "15e03ffbfeddb9c2aebc13dcb2a4a8f4", "monkey", "VGA", "VGA", 8357, Common::EN_ANY, Common::kPlatformPC }, { "15f588e887e857e8c56fe6ade4956168", "atlantis", "Floppy", "Floppy", -1, Common::ES_ESP, Common::kPlatformAmiga }, { "16542a7342a918bfe4ba512007d36c47", "FreddisFunShop", "HE 99L", "", -1, Common::EN_USA, Common::kPlatformUnknown }, - { "166553538ff320c69edafeee29525419", "samnmax", "", "CD", -1, Common::EN_ANY, Common::kPlatformMacintosh }, + { "166553538ff320c69edafeee29525419", "samnmax", "", "CD", 199195304, Common::EN_ANY, Common::kPlatformMacintosh }, { "16effd200aa6b8abe9c569c3e578814d", "freddi4", "HE 99", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows }, { "179879b6e35c1ead0d93aab26db0951b", "fbear", "HE 70", "", 13381, Common::EN_ANY, Common::kPlatformWindows }, { "17b5d5e6af4ae89d62631641d66d5a05", "indy3", "VGA", "VGA", -1, Common::IT_ITA, Common::kPlatformPC }, - { "17f7296f63c78642724f057fd8e736a7", "maniac", "NES", "", -1, Common::EN_GRB, Common::kPlatformNES }, + { "17f7296f63c78642724f057fd8e736a7", "maniac", "NES", "", 2082, Common::EN_GRB, Common::kPlatformNES }, { "17fa250eb72dae2dad511ba79c0b6b0a", "tentacle", "", "Demo", -1, Common::FR_FRA, Common::kPlatformPC }, { "182344899c2e2998fca0bebcd82aa81a", "atlantis", "", "CD", 12035, Common::EN_ANY, Common::kPlatformPC }, { "183d7464902d40d00800e8ee1f04117c", "maniac", "V2", "V2", 1988, Common::DE_DEU, Common::kPlatformPC }, @@ -130,13 +130,14 @@ static const MD5Table md5table[] = { { "2d388339d6050d8ccaa757b64633954e", "zak", "FM-TOWNS", "Demo", 7520, Common::EN_ANY, Common::kPlatformFMTowns }, { "2d4536a56e01da4b02eb021e7770afa2", "zak", "FM-TOWNS", "", 7520, Common::EN_ANY, Common::kPlatformFMTowns }, { "2d4acbdcfd8e374c9da8c2e7303a5cd0", "BluesBirthday", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, - { "2d624d1b214f7faf0094daea65c6d1a6", "maniac", "Apple II", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, + { "2d624d1b214f7faf0094daea65c6d1a6", "maniac", "Apple II", "", -1, Common::EN_ANY, Common::kPlatformApple2GS }, { "2d9d46f23cb07bbc90b8ad464d3e4ff8", "atlantis", "", "CD", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "2e85f7aa054930c692a5b1bed1dfc295", "football2002", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "2e8a1f76ea33bc5e04347646feee173d", "pajama3", "", "", -1, Common::DE_DEU, Common::kPlatformUnknown }, { "2fe369ad70f52a8cf7ad6077ee64f81a", "loom", "EGA", "EGA", -1, Common::DE_DEU, Common::kPlatformAmiga }, { "305d3dd57c96c65b017bc70c8c7cfb5e", "monkey", "CD", "CD", 8955, Common::DE_DEU, Common::kPlatformPC }, { "30ba1e825d4ad2b448143ae8df18482a", "pajama2", "HE 98.5", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown }, + { "30d1903b0715759af064be2127381cd0", "freddi", "HE 100", "", 34837, Common::DE_DEU, Common::kPlatformWii }, { "319a4dde52c7960b5aae8a1ec348d918", "monkey", "VGA", "VGA", -1, Common::DE_DEU, Common::kPlatformAmiga }, { "31aa57f460a3d12429f0552a46a90b39", "puttputt", "Demo", "Demo", 6150, Common::EN_ANY, Common::kPlatformPC }, { "31b8fda4c8c7413fa6b39997e776eba4", "loom", "FM-TOWNS", "", -1, Common::JA_JPN, Common::kPlatformFMTowns }, @@ -145,7 +146,7 @@ static const MD5Table md5table[] = { { "330f631502e381a4e199a3f7cb483c20", "indy3", "EGA", "EGA", -1, Common::DE_DEU, Common::kPlatformAmiga }, { "33e989f85da700e2014d00f345cab3d7", "puttrace", "HE 98.5", "", -1, Common::FR_FRA, Common::kPlatformWindows }, { "3433be9866ca4261b2d5d25374e3f243", "monkey", "VGA", "VGA", -1, Common::FR_FRA, Common::kPlatformAmiga }, - { "3486ede0f904789267d4bcc5537a46d4", "puttzoo", "", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh }, + { "3486ede0f904789267d4bcc5537a46d4", "puttzoo", "", "Demo", 14337, Common::EN_ANY, Common::kPlatformMacintosh }, { "356fb5f680b68251333016175935d126", "BluesABCTime", "HE CUP", "Preview", 4133436, Common::UNK_LANG, Common::kPlatformUnknown }, { "35a2d3040fa512f8232d9e443319d84d", "dig", "", "", 659335495, Common::EN_ANY, Common::kPlatformMacintosh }, { "362c1d281fb9899254cda66ad246c66a", "dig", "Demo", "Demo", 3472, Common::EN_ANY, Common::kPlatformUnknown }, @@ -167,6 +168,7 @@ static const MD5Table md5table[] = { { "3a3e592b074f595489f7f11e150c398d", "puttzoo", "HE 99", "Updated", -1, Common::EN_USA, Common::kPlatformWindows }, { "3a5d13675e9a23aedac0bac7730f0ac1", "samnmax", "", "CD", -1, Common::FR_FRA, Common::kPlatformMacintosh }, { "3a5ec90d556d4920976c5578bfbfaf79", "maniac", "NES", "", -1, Common::DE_DEU, Common::kPlatformNES }, + { "3ae7f002d9256b8bdf76aaf8a3a069f8", "freddi", "HE 100", "", 34837, Common::EN_GRB, Common::kPlatformWii }, { "3af61c5edf8e15b43dbafd285b2e9777", "puttcircus", "", "Demo", -1, Common::HE_ISR, Common::kPlatformWindows }, { "3b301b7892f883ce42ab4be6a274fea6", "samnmax", "Floppy", "Floppy", -1, Common::EN_ANY, Common::kPlatformPC }, { "3b832f4a90740bf22e9b8ed42ca0128c", "freddi4", "HE 99", "", -1, Common::EN_GRB, Common::kPlatformWindows }, @@ -183,7 +185,7 @@ static const MD5Table md5table[] = { { "425205754fa749f4f0b0dd9d09fa45fd", "football", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "430bc518017b6fac046f58bab6baad5d", "monkey2", "", "", -1, Common::JA_JPN, Common::kPlatformFMTowns }, { "439a7f4adf510489981ac52308e7d7a2", "maniac", "C64", "", -1, Common::DE_DEU, Common::kPlatformC64 }, - { "45082a5c9f42ba14dacfe1fdeeba819d", "freddicove", "HE 100", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, + { "45082a5c9f42ba14dacfe1fdeeba819d", "freddicove", "HE 100", "Demo", 18422, Common::EN_ANY, Common::kPlatformUnknown }, { "45152f7cf2ba8f43cf8a8ea2e740ae09", "monkey", "VGA", "VGA", 8357, Common::ES_ESP, Common::kPlatformPC }, { "4521138d15d1fd7649c31fb981746231", "pajama2", "HE 98.5", "Demo", -1, Common::DE_DEU, Common::kPlatformUnknown }, { "46b53fd430adcfbed791b48a0d4b079f", "funpack", "", "", -1, Common::EN_ANY, Common::kPlatformPC }, @@ -196,6 +198,7 @@ static const MD5Table md5table[] = { { "49a1739981a89066b1121fac04b710f4", "spyfox2", "HE CUP", "Preview", 5756234, Common::UNK_LANG, Common::kPlatformUnknown }, { "4aa93cb30e485b728504ba3a693f12bf", "pajama", "HE 100", "", -1, Common::RU_RUS, Common::kPlatformWindows }, { "4af4a6b248103c1fe9edef619677f540", "puttmoon", "", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh }, + { "4afb734df8315ee412669c812d4cf0a1", "freddi", "HE 100", "", 34837, Common::FR_FRA, Common::kPlatformWii }, { "4ba37f835be11a59d969f90f272f575b", "water", "HE 80", "", -1, Common::EN_USA, Common::kPlatformUnknown }, { "4ba7fb331296c283e73d8f5b2096e551", "samnmax", "", "CD", -1, Common::ES_ESP, Common::kPlatformUnknown }, { "4bedb49943df95a9c900a5a82ccbe9de", "ft", "", "", -1, Common::FR_FRA, Common::kPlatformUnknown }, @@ -225,11 +228,12 @@ static const MD5Table md5table[] = { { "5262a27afcaee04e5c4900220bd463e7", "PuttsFunShop", "", "", -1, Common::EN_USA, Common::kPlatformUnknown }, { "52a4bae0746a11d7b1e8554e91a6645c", "zak", "V2", "V2", -1, Common::FR_FRA, Common::kPlatformPC }, { "53e94115b55dd51d4b8ff0871aa1df1e", "spyfox", "", "Demo", 20103, Common::EN_ANY, Common::kPlatformUnknown }, - { "54a936ad06161ff7bfefcb96200f7bff", "monkey", "VGA", "VGA Demo", -1, Common::EN_ANY, Common::kPlatformAmiga }, + { "54a936ad06161ff7bfefcb96200f7bff", "monkey", "VGA", "VGA Demo", 7617, Common::EN_ANY, Common::kPlatformAmiga }, { "55518cd73cf9c6d23ea29c51ee06bdfe", "ft", "", "", -1, Common::IT_ITA, Common::kPlatformUnknown }, { "55e4cc866ff9046824e1c638ba2b8c7f", "ft", "", "", -1, Common::RU_RUS, Common::kPlatformUnknown }, { "55f4e9402bec2bded383843123f37c5c", "pajama2", "HE 98.5", "", -1, Common::DE_DEU, Common::kPlatformWindows }, { "566165a7338fa11029e7c14d94fa70d0", "freddi", "HE 73", "Demo", 9800, Common::EN_ANY, Common::kPlatformWindows }, + { "56b5922751be7ffd771b38dda56b028b", "freddi", "HE 100", "", 34837, Common::NL_NLD, Common::kPlatformWii }, { "5719fc8a13b4638b78d9d8d12f091f94", "puttrace", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformWindows }, { "5798972220cd458be2626d54c80f71d7", "atlantis", "Floppy", "Floppy", -1, Common::IT_ITA, Common::kPlatformAmiga }, { "57a17febe2183f521250e55d55b83e60", "PuttTime", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformWindows }, @@ -242,7 +246,7 @@ static const MD5Table md5table[] = { { "59d5cfcc5e672a6e07baae01328b918b", "PuttTime", "HE 90", "Demo", -1, Common::FR_FRA, Common::kPlatformUnknown }, { "5a35e36fd777e9c37a49c5b2faca52f9", "loom", "EGA", "EGA Demo", 6108, Common::EN_ANY, Common::kPlatformPC }, { "5b08000a9c47b2887df6506ac767ca68", "fbear", "HE 62", "", -1, Common::EN_ANY, Common::kPlatform3DO }, - { "5bd335265a61caa3d78956ad9f88ba23", "football", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, + { "5bd335265a61caa3d78956ad9f88ba23", "football", "", "Demo", 23135, Common::EN_ANY, Common::kPlatformUnknown }, { "5c21fc49aee8f46e58fef21579e614a1", "thinker1", "", "", -1, Common::EN_USA, Common::kPlatformUnknown }, { "5d88b9d6a88e6f8e90cded9d01b7f082", "loom", "VGA", "VGA", 8307, Common::EN_ANY, Common::kPlatformPC }, { "5dda73606533d66a4c3f4f9ea6e842af", "farm", "", "", 87061, Common::RU_RUS, Common::kPlatformWindows }, @@ -357,6 +361,7 @@ static const MD5Table md5table[] = { { "87df3e0074624040407764b7c5e710b9", "pajama", "", "Demo", 18354, Common::NL_NLD, Common::kPlatformWindows }, { "87f6e8037b7cc996e13474b491a7a98e", "maniac", "V2", "V2", -1, Common::IT_ITA, Common::kPlatformPC }, { "8801fb4a1200b347f7a38523339526dd", "jungle", "", "", -1, Common::EN_ANY, Common::kPlatformWindows }, + { "880c5ca5b944648b3f8b03feb41705a8", "freddi", "HE 100", "", 34837, Common::SE_SWE, Common::kPlatformWii }, { "883af4b0af4f77a92f1dcf1d0a283140", "tentacle", "", "CD", -1, Common::ES_ESP, Common::kPlatformUnknown }, { "898ce8eb1234a955ef75e87141902bb3", "freddi3", "", "", -1, Common::RU_RUS, Common::kPlatformWindows }, { "898eaa21f79cf8d4f08db856244689ff", "pajama", "HE 99", "Updated", 66505, Common::EN_ANY, Common::kPlatformWindows }, @@ -366,13 +371,13 @@ static const MD5Table md5table[] = { { "8aed489aba45d2b9fb8a04079c9c6e6a", "baseball", "HE CUP", "Preview", 12876596, Common::UNK_LANG, Common::kPlatformUnknown }, { "8afb3cf9f95abf208358e984f0c9e738", "funpack", "", "", -1, Common::EN_ANY, Common::kPlatform3DO }, { "8bdb0bf87b5e303dd35693afb9351215", "ft", "", "", -1, Common::DE_DEU, Common::kPlatformUnknown }, - { "8d479e36f35e80257dfc102cf4b8a912", "farm", "HE 72", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows }, + { "8d479e36f35e80257dfc102cf4b8a912", "farm", "HE 72", "Demo", 34333, Common::EN_ANY, Common::kPlatformWindows }, { "8de13897f0121c79d29a2377159f9ad0", "socks", "HE 99", "Updated", -1, Common::EN_ANY, Common::kPlatformWindows }, { "8e3241ddd6c8dadf64305e8740d45e13", "balloon", "HE 100", "Updated", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "8e4ee4db46954bfe2912e259a16fad82", "monkey2", "", "", -1, Common::FR_FRA, Common::kPlatformPC }, { "8e9417564f33790815445b2136efa667", "atlantis", "", "CD", 11915, Common::JA_JPN, Common::kPlatformMacintosh }, { "8e9830a6f2702be5b22c8fa0a6aaf977", "freddi2", "HE 80", "", -1, Common::NL_NLD, Common::kPlatformMacintosh }, - { "8eb84cee9b429314c7f0bdcf560723eb", "monkey", "FM-TOWNS", "", -1, Common::EN_ANY, Common::kPlatformFMTowns }, + { "8eb84cee9b429314c7f0bdcf560723eb", "monkey", "FM-TOWNS", "", 9925, Common::EN_ANY, Common::kPlatformFMTowns }, { "8ee63cafb1fe9d62aa0d5a23117e70e7", "freddi2", "HE 100", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown }, { "8f3758ff98c9c5d78e5d635222cad026", "atlantis", "Floppy", "Floppy", -1, Common::IT_ITA, Common::kPlatformPC }, { "8fec68383202d38c0d25e9e3b757c5df", "comi", "Demo", "Demo", 18041, Common::UNK_LANG, Common::kPlatformWindows }, @@ -413,7 +418,7 @@ static const MD5Table md5table[] = { { "9d7b67be003fea60be4dcbd193611936", "ft", "Demo", "Demo", 11164, Common::EN_ANY, Common::kPlatformMacintosh }, { "9dc02577bf50d4cfaf3de3fbac06fbe2", "puttmoon", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "9e5e0fb43bd22f4628719b7501adb717", "monkey", "No AdLib", "EGA", -1, Common::FR_FRA, Common::kPlatformAtariST }, - { "9fd66fb3b04703bd50da4356e4202558", "spyfox2", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh }, + { "9fd66fb3b04703bd50da4356e4202558", "spyfox2", "", "", 51295, Common::EN_ANY, Common::kPlatformMacintosh }, { "a00554c31d623fdb9fcb0f924b89b42b", "loom", "EGA", "EGA Demo", -1, Common::EN_ANY, Common::kPlatformPC }, { "a01fab4a64d47b96e2e58e6b0f825cc7", "monkey", "VGA", "VGA", 8347, Common::FR_FRA, Common::kPlatformPC }, { "a095616d2d23ccf43b8e257711202cba", "football2002", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, @@ -430,6 +435,7 @@ static const MD5Table md5table[] = { { "a561d2e2413cc1c71d5a1bf87bf493ea", "lost", "HE 100", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown }, { "a56e8d9d4281c53c3f63c9bd22a59e21", "catalog", "HE CUP", "Preview", 10978342, Common::EN_ANY, Common::kPlatformUnknown }, { "a570381b028972d891052ee1e51dc011", "maniac", "V2", "V2", 1988, Common::EN_ANY, Common::kPlatformAtariST }, + { "a59a438cb182124c30c4447d8ed469e9", "freddi", "HE 100", "", 34837, Common::NB_NOR, Common::kPlatformWii }, { "a5c5388da9bf0e6662fdca8813a79d13", "farm", "", "", 86962, Common::EN_ANY, Common::kPlatformWindows }, { "a654fb60c3b67d6317a7894ffd9f25c5", "pajama3", "", "Demo", -1, Common::EN_USA, Common::kPlatformUnknown }, { "a7cacad9c40c4dc9e1812abf6c8af9d5", "puttcircus", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, @@ -489,13 +495,13 @@ static const MD5Table md5table[] = { { "c4787c3e8b5e2dfda90850ee800af00f", "zak", "V2", "V2", -1, Common::FR_FRA, Common::kPlatformPC }, { "c4ffae9fac495475d6bc3343ccc8faf9", "Soccer2004", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "c5cc7cba02a2fbd539c4439e775b0536", "puttzoo", "HE 99", "Updated", 43470, Common::DE_DEU, Common::kPlatformWindows }, - { "c5d10e190d4b4d59114b824f2fdbd00e", "loom", "FM-TOWNS", "", -1, Common::EN_ANY, Common::kPlatformFMTowns }, + { "c5d10e190d4b4d59114b824f2fdbd00e", "loom", "FM-TOWNS", "", 7540, Common::EN_ANY, Common::kPlatformFMTowns }, { "c63ee46143ba65f9ce14cf539ca51bd7", "atlantis", "Floppy", "Floppy", -1, Common::EN_ANY, Common::kPlatformPC }, { "c666a998af90d81db447eccba9f72c8d", "monkey", "No AdLib", "EGA", -1, Common::EN_ANY, Common::kPlatformAtariST }, { "c6907d44f1166941d982864cd42cdc89", "pajama2", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown }, { "c782fbbe74a987c3df8ac73cd3e289ed", "freddi", "HE 73", "", -1, Common::SE_SWE, Common::kPlatformMacintosh }, { "c7890e038806df2bb5c0c8c6f1986ea2", "monkey", "VGA", "VGA", -1, Common::EN_ANY, Common::kPlatformPC }, - { "c7be10f775404fd9785a8b92a06d240c", "atlantis", "", "", -1, Common::EN_ANY, Common::kPlatformFMTowns }, + { "c7be10f775404fd9785a8b92a06d240c", "atlantis", "", "", 12030, Common::EN_ANY, Common::kPlatformFMTowns }, { "c7c492a107ec520d7a7943037d0ca54a", "freddi", "HE 71", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows }, { "c83079157ec765a28de445aec9768d60", "tentacle", "", "Demo", 7477, Common::EN_ANY, Common::kPlatformUnknown }, { "c8575e0b973ff1723aba6cd92c642db2", "puttrace", "HE 99", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows }, @@ -519,7 +525,7 @@ static const MD5Table md5table[] = { { "cf4ef315214c7d8cdab6302cdb7e50db", "freddi", "HE 73", "Demo", -1, Common::DE_DEU, Common::kPlatformWindows }, { "cf8d13446ec6cb6222287a925fd47c1d", "baseball", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "cf8ef3a1fb483c5c4b1c584d1167b2c4", "freddi", "HE 73", "", -1, Common::DE_DEU, Common::kPlatformWindows }, - { "cf90b4db5486ef798db78fe6fbf897e5", "pajama3", "", "Demo", -1, Common::EN_USA, Common::kPlatformWindows }, + { "cf90b4db5486ef798db78fe6fbf897e5", "pajama3", "", "Demo", 13902, Common::EN_USA, Common::kPlatformWindows }, { "d00ffc8c32d17e575fd985d435d2eb88", "arttime", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "d0549508a06bbb9f99ed19c9e97891f3", "football2002", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "d06fbe28818fef7bfc45c2cdf0c0849d", "zak", "V2", "V2", -1, Common::DE_DEU, Common::kPlatformPC }, @@ -554,14 +560,14 @@ static const MD5Table md5table[] = { { "dbf4d59d70b826733f379f998354d350", "BluesBirthday", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "dcf0119a90451a7d6e0f1920931ba130", "freddi4", "HE 99", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows }, { "dd30a53035393baa5a5e222e716559af", "maniac", "V2", "V2", -1, Common::FR_FRA, Common::kPlatformAtariST }, - { "de4efb910210736813c9a1185384bace", "puttzoo", "HE 72", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows }, + { "de4efb910210736813c9a1185384bace", "puttzoo", "HE 72", "Demo", 14337, Common::EN_ANY, Common::kPlatformWindows }, { "debe337f73d660e951ece7c1f1c81add", "zak", "V2", "V2", -1, Common::EN_ANY, Common::kPlatformPC }, { "defb8cb9ec4b0f91acfb6b61c6129ad9", "PuttTime", "HE 99", "", -1, Common::RU_RUS, Common::kPlatformWindows }, { "df03ee021aa9b81d90cab9c26da07614", "indy3", "EGA", "EGA", -1, Common::IT_ITA, Common::kPlatformAmiga }, { "df047cc4792150f601290357566d36a6", "freddi", "HE 90", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown }, { "e01acc8c12ef44e8f778fe87e5f90f4e", "fbpack", "", "", -1, Common::EN_ANY, Common::kPlatform3DO }, { "e03ed1474ec14de78359970e0457a820", "freddi4", "HE 99", "Demo", -1, Common::EN_GRB, Common::kPlatformWindows }, - { "e144f5f49d9241d2a9dee2576b3d09cb", "airport", "", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows }, + { "e144f5f49d9241d2a9dee2576b3d09cb", "airport", "", "Demo", 51152, Common::EN_ANY, Common::kPlatformWindows }, { "e17db1ddf91b39ca6bbc8ad3ed19e883", "monkey", "FM-TOWNS", "", -1, Common::JA_JPN, Common::kPlatformFMTowns }, { "e246e02db9630533a40d99c9f54a8e01", "monkey2", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "e361a7058ed8e8ebb462663c0a3ae8d6", "puttputt", "HE 62", "", -1, Common::HE_ISR, Common::kPlatformPC }, @@ -576,12 +582,13 @@ static const MD5Table md5table[] = { { "e6cd81b25ab1453a8a6d3482118c391e", "pass", "", "", 7857, Common::EN_ANY, Common::kPlatformPC }, { "e72bb4c2b613db2cf50f89ff6350e70a", "ft", "", "", -1, Common::ES_ESP, Common::kPlatformUnknown }, { "e781230da44a44e2f0770edb2b3b3633", "maniac", "V2", "V2", -1, Common::EN_ANY, Common::kPlatformAmiga }, + { "e8d0697906e53fee8b7e9f5652696da8", "atlantis", "", "CD", 11915, Common::JA_JPN, Common::kPlatformPC }, { "e94c7cc3686fce406d3c91b5eae5a72d", "zak", "V2", "V2", -1, Common::EN_ANY, Common::kPlatformAmiga }, { "e95cf980719c0be078fb68a67af97b4a", "funpack", "", "", -1, Common::JA_JPN, Common::kPlatform3DO }, { "e98b982ceaf9d253d730bde8903233d6", "monkey", "EGA", "EGA", -1, Common::DE_DEU, Common::kPlatformPC }, { "eae95b2b3546d8ba86ae1d397c383253", "dog", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "eb700bb73ca1cc44a1ad5e4b1a4bdeaf", "indy3", "EGA", "EGA", 5361, Common::DE_DEU, Common::kPlatformPC }, - { "ebd0b2c8a387f18887282afe6cad894a", "spyozon", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, + { "ebd0b2c8a387f18887282afe6cad894a", "spyozon", "", "Demo", 15317, Common::EN_ANY, Common::kPlatformUnknown }, { "ebd324dcf06a4c49e1ba5c231eee1060", "freddi4", "HE 99", "Demo", -1, Common::EN_USA, Common::kPlatformUnknown }, { "ecc4340c2b801f5af8da4e00c0e432d9", "puttcircus", "", "", -1, Common::NL_NLD, Common::kPlatformUnknown }, { "ed2b074bc3166087a747acb2a3c6abb0", "freddi3", "HE 98.5", "Demo", -1, Common::DE_DEU, Common::kPlatformUnknown }, @@ -617,7 +624,7 @@ static const MD5Table md5table[] = { { "fbbbb38a81fc9d6a61d509278390a290", "farm", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "fbdd947d21e8f5bac6d6f7a316af1c5a", "spyfox", "", "Demo", 15693, Common::EN_ANY, Common::kPlatformUnknown }, { "fc53ce0e5f6562b1c1e1b4b8203acafb", "samnmax", "Floppy", "Floppy", -1, Common::ES_ESP, Common::kPlatformPC }, - { "fc6b6148e80d67939d9a18697c0f626a", "monkey", "EGA", "EGA", -1, Common::DE_DEU, Common::kPlatformPC }, + { "fc6b6148e80d67939d9a18697c0f626a", "monkey", "EGA", "EGA", 8367, Common::DE_DEU, Common::kPlatformPC }, { "fc8d197a22146e74766e9cb0cfcaf1da", "freddi2", "HE 80", "Demo", 27298, Common::EN_ANY, Common::kPlatformUnknown }, { "fcb78ebecab2757264c590890c319cc5", "PuttTime", "HE 85", "", -1, Common::NL_NLD, Common::kPlatformUnknown }, { "fce4b8010704b103acfeea9413788f32", "freddi2", "HE 80", "", -1, Common::DE_DEU, Common::kPlatformUnknown }, diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 2d83622f05..86ec8c4748 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -1634,28 +1634,28 @@ void ScummEngine_v100he::resetScumm() { #endif void ScummEngine::setupMusic(int midi) { - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(midi); - _native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(midi); + _native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); - switch (midiDriver) { - case MD_NULL: + switch (MidiDriver::getMusicType(dev)) { + case MT_NULL: _musicType = MDT_NONE; break; - case MD_PCSPK: - case MD_PCJR: + case MT_PCSPK: + case MT_PCJR: _musicType = MDT_PCSPK; break; - case MD_CMS: + //case MT_CMS: #if 1 _musicType = MDT_ADLIB; #else _musicType = MDT_CMS; // Still has number of bugs, disable by default #endif break; - case MD_TOWNS: + case MT_TOWNS: _musicType = MDT_TOWNS; break; - case MD_ADLIB: + case MT_ADLIB: _musicType = MDT_ADLIB; break; default: @@ -1707,7 +1707,7 @@ void ScummEngine::setupMusic(int midi) { if (!_mixer->isReady()) { warning("Sound mixer initialization failed"); if (_musicType == MDT_ADLIB || _musicType == MDT_PCSPK || _musicType == MDT_CMS) { - midiDriver = MD_NULL; + dev = 0; _musicType = MDT_NONE; warning("MIDI driver depends on sound mixer, switching to null MIDI driver"); } @@ -1735,11 +1735,11 @@ void ScummEngine::setupMusic(int midi) { } else if (_game.platform == Common::kPlatformAmiga && _game.version <= 4) { _musicEngine = new Player_V4A(this, _mixer); } else if (_game.id == GID_MANIAC && _game.version == 1) { - _musicEngine = new Player_V1(this, _mixer, midiDriver != MD_PCSPK); + _musicEngine = new Player_V1(this, _mixer, MidiDriver::getMusicType(dev) != MT_PCSPK); } else if (_game.version <= 2) { - _musicEngine = new Player_V2(this, _mixer, midiDriver != MD_PCSPK); + _musicEngine = new Player_V2(this, _mixer, MidiDriver::getMusicType(dev) != MT_PCSPK); } else if ((_musicType == MDT_PCSPK) && (_game.version > 2 && _game.version <= 4)) { - _musicEngine = new Player_V2(this, _mixer, midiDriver != MD_PCSPK); + _musicEngine = new Player_V2(this, _mixer, MidiDriver::getMusicType(dev) != MT_PCSPK); } else if (_musicType == MDT_CMS) { _musicEngine = new Player_V2CMS(this, _mixer); } else if (_game.platform == Common::kPlatform3DO && _game.heversion <= 62) { @@ -1749,12 +1749,12 @@ void ScummEngine::setupMusic(int midi) { MidiDriver *adlibMidiDriver = 0; if (_musicType != MDT_ADLIB) - nativeMidiDriver = MidiDriver::createMidi(midiDriver); + nativeMidiDriver = MidiDriver::createMidi(dev); if (nativeMidiDriver != NULL && _native_mt32) nativeMidiDriver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); bool multi_midi = ConfMan.getBool("multi_midi") && _musicType != MDT_NONE && (midi & MDT_ADLIB); if (_musicType == MDT_ADLIB || multi_midi) { - adlibMidiDriver = MidiDriver_ADLIB_create(); + adlibMidiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(MDT_ADLIB)); adlibMidiDriver->property(MidiDriver::PROP_OLD_ADLIB, (_game.features & GF_SMALL_HEADER) ? 1 : 0); } @@ -1769,7 +1769,7 @@ void ScummEngine::setupMusic(int midi) { // YM2162 driver can't handle midi->getPercussionChannel(), NULL shouldn't init MT-32/GM/GS if ((midi != MDT_TOWNS) && (midi != MDT_NONE)) { _imuse->property(IMuse::PROP_NATIVE_MT32, _native_mt32); - if (midiDriver != MD_MT32) // MT-32 Emulation shouldn't be GM/GS initialized + if (MidiDriver::getMusicType(dev) != MT_MT32) // MT-32 Emulation shouldn't be GM/GS initialized _imuse->property(IMuse::PROP_GS, _enable_gs); } if (_game.heversion >= 60 || midi == MDT_TOWNS) { @@ -2081,6 +2081,12 @@ void ScummEngine::scummLoop_updateScummVars() { if (_game.version >= 7) { VAR(VAR_CAMERA_POS_X) = camera._cur.x; VAR(VAR_CAMERA_POS_Y) = camera._cur.y; + } else if (_game.platform == Common::kPlatformNES) { + // WORKAROUND: + // Since there are 2 2-stripes wide borders in MM NES screen, + // we have to compensate for it here. This fixes paning effects. + // Fixes bug #1328120: "MANIACNES: Screen width incorrect, camera halts sometimes" + VAR(VAR_CAMERA_POS_X) = (camera._cur.x >> V12_X_SHIFT) + 2; } else if (_game.version <= 2) { VAR(VAR_CAMERA_POS_X) = camera._cur.x >> V12_X_SHIFT; } else { diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp index 98fa3d0e4a..840f8fc779 100644 --- a/engines/scumm/sound.cpp +++ b/engines/scumm/sound.cpp @@ -1788,7 +1788,7 @@ static void convertADResource(ResourceManager *res, const GameSettings& game, in // There is a constant delay of ppqn/3 before the music starts. if (ppqn / 3 >= 128) - *ptr++ = (ppqn / 3 >> 7) | 0x80; + *ptr++ = ((ppqn / 3) >> 7) | 0x80; *ptr++ = ppqn / 3 & 0x7f; // Now copy the actual music data diff --git a/engines/scumm/string.cpp b/engines/scumm/string.cpp index 480e18e514..62fdf48440 100644 --- a/engines/scumm/string.cpp +++ b/engines/scumm/string.cpp @@ -1351,6 +1351,8 @@ void ScummEngine_v7::loadLanguageBundle() { // File contains Korean text (Hangul). just ignore it } else if (*ptr == 'j') { // File contains Japanese text. just ignore it + } else if (*ptr == 'c') { + // File contains Chinese text. just ignore it } else if (*ptr == 'e') { // File is encoded! enc = 0x13; diff --git a/engines/scumm/verbs.h b/engines/scumm/verbs.h index 96a49a7ced..83e924edac 100644 --- a/engines/scumm/verbs.h +++ b/engines/scumm/verbs.h @@ -31,7 +31,7 @@ namespace Scumm { /** - * The area in which some click (or key press) occured and which is passed + * The area in which some click (or key press) occurred and which is passed * to the input script. */ enum ClickArea { diff --git a/engines/sky/sky.cpp b/engines/sky/sky.cpp index 9ea20aafc6..45b3cab947 100644 --- a/engines/sky/sky.cpp +++ b/engines/sky/sky.cpp @@ -259,16 +259,16 @@ Common::Error SkyEngine::init() { _systemVars.gameVersion = _skyDisk->determineGameVersion(); - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI); - if (midiDriver == MD_ADLIB) { + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32); + if (MidiDriver::getMusicType(dev) == MT_ADLIB) { _systemVars.systemFlags |= SF_SBLASTER; _skyMusic = new AdLibMusic(_mixer, _skyDisk); } else { _systemVars.systemFlags |= SF_ROLAND; - if ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")) - _skyMusic = new MT32Music(MidiDriver::createMidi(midiDriver), _skyDisk); + if ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")) + _skyMusic = new MT32Music(MidiDriver::createMidi(dev), _skyDisk); else - _skyMusic = new GmMusic(MidiDriver::createMidi(midiDriver), _skyDisk); + _skyMusic = new GmMusic(MidiDriver::createMidi(dev), _skyDisk); } if (isCDVersion()) { diff --git a/engines/sword1/music.cpp b/engines/sword1/music.cpp index 91c943472c..23cc30e4b1 100644 --- a/engines/sword1/music.cpp +++ b/engines/sword1/music.cpp @@ -107,7 +107,7 @@ bool MusicHandle::play(const char *fileBase, bool loop) { if (!_audioSource) { sprintf(fileName, "%s.aif", fileBase); if (_file.open(fileName)) - _audioSource = Audio::makeLoopingAudioStream(Audio::makeAIFFStream(_file), loop ? 0 : 1); + _audioSource = Audio::makeLoopingAudioStream(Audio::makeAIFFStream(&_file, DisposeAfterUse::NO), loop ? 0 : 1); } if (!_audioSource) diff --git a/engines/teenagent/detection.cpp b/engines/teenagent/detection.cpp index 258bd982ed..a2dab9658d 100644 --- a/engines/teenagent/detection.cpp +++ b/engines/teenagent/detection.cpp @@ -91,7 +91,9 @@ static const ADParams detectionParams = { "teenagent", 0, 0, - Common::GUIO_NONE + Common::GUIO_NONE, + 1, + 0 }; #define MAX_SAVES 20 diff --git a/engines/tinsel/cliprect.cpp b/engines/tinsel/cliprect.cpp index 69a71b874f..5f287d3eab 100644 --- a/engines/tinsel/cliprect.cpp +++ b/engines/tinsel/cliprect.cpp @@ -28,17 +28,15 @@ #include "tinsel/graphics.h" // normal object drawing #include "tinsel/object.h" #include "tinsel/palette.h" +#include "tinsel/tinsel.h" // for _vm namespace Tinsel { -/** list of all clip rectangles */ -static RectList s_rectList; - /** * Resets the clipping rectangle allocator. */ void ResetClipRect() { - s_rectList.clear(); + _vm->_clipRects.clear(); } /** @@ -46,11 +44,11 @@ void ResetClipRect() { * @param pClip clip rectangle dimensions to allocate */ void AddClipRect(const Common::Rect &pClip) { - s_rectList.push_back(pClip); + _vm->_clipRects.push_back(pClip); } const RectList &GetClipRects() { - return s_rectList; + return _vm->_clipRects; } /** @@ -175,6 +173,8 @@ void FindMovingObjects(OBJECT *pObjList, Common::Point *pWin, Common::Rect *pCli * the total number of clip rectangles. */ void MergeClipRect() { + RectList &s_rectList = _vm->_clipRects; + if (s_rectList.size() <= 1) return; diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp index 70a2f475ee..d6bdad6032 100644 --- a/engines/tinsel/detection.cpp +++ b/engines/tinsel/detection.cpp @@ -75,549 +75,7 @@ static const PlainGameDescriptor tinselGames[] = { {0, 0} }; - -namespace Tinsel { - -using Common::GUIO_NONE; -using Common::GUIO_NOSPEECH; -using Common::GUIO_NOSFX; -using Common::GUIO_NOMUSIC; - -static const TinselGameDescription gameDescriptions[] = { - - // Note: The following is the (hopefully) definitive list of version details: - // TINSEL_V0: Used only by the Discworld 1 demo - this used a more primitive version - // of the Tinsel engine and graphics compression - // TINSEL_V1: There were two versions of the Discworld 1 game - the first used .GRA - // files, and the second used .SCN files. The second also provided some fixes to - // various script bugs and coding errors, but is still considered TINSEL_V1, - // as both game versions work equally well with the newer code. - // TINSEL_V2: The Discworld 2 game used this updated version of the Tinsel 1 engine, - // and as far as we know there aren't any variations of this engine. - - { // Floppy Demo V0 from http://www.adventure-treff.de/specials/dl_demos.php - { - "dw", - "Floppy Demo", - AD_ENTRY1s("dw.gra", "ce1b57761ba705221bcf70955b827b97", 441192), - //AD_ENTRY1s("dw.scn", "ccd72f02183d0e96b6e7d8df9492cda8", 23308), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO, - GUIO_NOSPEECH | GUIO_NOSFX | GUIO_NOMUSIC - }, - GID_DW1, - 0, - GF_DEMO, - TINSEL_V0, - }, - - { // CD Demo V1 version, with *.gra files - { - "dw", - "CD Demo", - { - {"dw.gra", 0, "ef5a2518c9e205f786f5a4526396e661", 781676}, - {"english.smp", 0, NULL, -1}, - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD, - TINSEL_V1, - }, - - { // Multilingual Floppy V1 with *.gra files. - // Note: It contains no english subtitles. - { - "dw", - "Floppy", - { - {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, - {"french.txt", 0, NULL, -1}, - {"german.txt", 0, NULL, -1}, - {"italian.txt", 0, NULL, -1}, - {"spanish.txt", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - GUIO_NOSPEECH - }, - GID_DW1, - 0, - GF_FLOPPY | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // Floppy V1 version, with *.gra files - { - "dw", - "Floppy", - AD_ENTRY1s("dw.gra", "c8808ccd988d603dd35dff42013ae7fd", 781656), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - GID_DW1, - 0, - GF_FLOPPY | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // CD V1 version, with *.gra files (same as the floppy one, with english.smp) - { - "dw", - "CD", - { - {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, - {"english.smp", 0, NULL, -1}, - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // Italian CD with english speech and *.gra files. - // Note: It contains only italian subtitles, but inside english.txt - { - "dw", - "CD", - { - {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, - {"english.txt", 0, "15f0703f85477d7fab4280bf938b61c1", 237774}, - {"english.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::IT_ITA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // Multilingual CD with english speech and *.gra files. - // Note: It contains no english subtitles. - { - "dw", - "CD", - { - {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, - {"english.smp", 0, NULL, -1}, - {"french.txt", 0, NULL, -1}, - {"german.txt", 0, NULL, -1}, - {"italian.txt", 0, NULL, -1}, - {"spanish.txt", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { - { - "dw", - "CD", - { - {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, - {"english.smp", 0, NULL, -1}, - {"french.txt", 0, NULL, -1}, - {"german.txt", 0, NULL, -1}, - {"italian.txt", 0, NULL, -1}, - {"spanish.txt", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - { - { - "dw", - "CD", - { - {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, - {"english.smp", 0, NULL, -1}, - {"french.txt", 0, NULL, -1}, - {"german.txt", 0, NULL, -1}, - {"italian.txt", 0, NULL, -1}, - {"spanish.txt", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::IT_ITA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - { - { - "dw", - "CD", - { - {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, - {"english.smp", 0, NULL, -1}, - {"french.txt", 0, NULL, -1}, - {"german.txt", 0, NULL, -1}, - {"italian.txt", 0, NULL, -1}, - {"spanish.txt", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::ES_ESP, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // English CD v2 - { - "dw", - "CD", - { - {"dw.scn", 0, "70955425870c7720d6eebed903b2ef41", 776188}, - {"english.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // Hebrew CD v2 - { - "dw", - "CD", - { - {"dw.scn", 0, "759d1374b4f02af6d52fc07c96679936", 770780}, - {"english.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::HE_ISR, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // Discworld PSX CD - { - "dw", - "CD", - { - {"english.txt", 0, "7526cfc3a64e00f223795de476b4e2c9", 230326}, - {NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPSX, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // multilanguage PSX demo - { - "dw", - "CD demo", - { - {"french.txt", 0, "e7020d35f58d0d187052ac406d86cc87", 273914}, - {"german.txt", 0, "52f0a01e0ff0d340b02a36fd5109d705", 263942}, - {"italian.txt", 0, "15f0703f85477d7fab4280bf938b61c1", 239834}, - {"spanish.txt", 0, "c324170c3f1922c605c5cc09ba265aa5", 236702}, - {"english.txt", 0, "7526cfc3a64e00f223795de476b4e2c9", 230326}, - {NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPSX, - ADGF_DEMO, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_SCNFILES, - TINSEL_V1, - }, - -#if 0 - { // English Saturn CD - { - "dw", - "CD", - { - {"dw.scn", 0, "6803f293c88758057cc685b9437f7637", 382248}, - {"english.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, -#endif - -#if 0 - { // Mac multilanguage CD - { - "dw", - "CD", - { - {"dw.scn", 0, "cfc40a8d5d476a1c9d3abf826fa46f8c", 1265532}, - {"english.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - -#endif - - { // German CD re-release "Neon Edition" - // Note: This release has ENGLISH.TXT (with german content) instead of GERMAN.TXT - { - "dw", - "CD", - AD_ENTRY1s("dw.scn", "6182c7986eaec893c62fb6ea13a9f225", 774556), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // Russian Discworld 1 - { - "dw", - "CD", - { - {"dw.scn", 0, "133041bde59d05c1bf084fd6f1bdce4b", 776524}, - {"english.txt", 0, "f73dcbd7b136b37c2adf7c9448ea336d", 231821}, - {"english.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::RU_RUS, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // European/Australian Discworld 2 release - { - "dw2", - "CD", - { - {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, - {"english1.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::EN_GRB, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW2, - 0, - GF_CD | GF_SCNFILES, - TINSEL_V2, - }, - - { // US Discworld 2 release - { - "dw2", - "CD", - { - {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, - {"us1.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::EN_USA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW2, - 0, - GF_CD | GF_SCNFILES, - TINSEL_V2, - }, - - { // French version of Discworld 2 - { - "dw2", - "CD", - { - {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, - {"french1.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::FR_FRA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW2, - 0, - GF_CD | GF_SCNFILES, - TINSEL_V2, - }, - - { // German Discworld 2 re-release "Neon Edition" - { - "dw2", - "CD", - { - {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, - {"german1.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW2, - 0, - GF_CD | GF_SCNFILES, - TINSEL_V2, - }, - - { // Italian/Spanish Discworld 2 - { - "dw2", - "CD", - { - {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, - {"english1.smp", 0, NULL, -1}, - {"italian1.txt", 0, "d443249f8b55489b5888c227b9096f4e", 246495}, - {NULL, 0, NULL, 0} - }, - Common::IT_ITA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW2, - 0, - GF_CD | GF_SCNFILES, - TINSEL_V2, - }, - { - { - "dw2", - "CD", - { - {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, - {"english1.smp", 0, NULL, -1}, - {"spanish1.txt", 0, "bc6e147c5f542db228ac577357e4d897", 230323}, - {NULL, 0, NULL, 0} - }, - Common::ES_ESP, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW2, - 0, - GF_CD | GF_SCNFILES, - TINSEL_V2, - }, - - { // Russian Discworld 2 release by Fargus - { - "dw2", - "CD", - { - {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, - {"english1.smp", 0, NULL, -1}, - {"english1.txt", 0, "b522e19d7b2cd7b85e50e36fe48e36a9", 274444}, - {NULL, 0, NULL, 0} - }, - Common::RU_RUS, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW2, - 0, - GF_CD | GF_SCNFILES, - TINSEL_V2, - }, - - { AD_TABLE_END_MARKER, 0, 0, 0, 0 } -}; - -} // End of namespace Tinsel +#include "tinsel/detection_tables.h" static const ADParams detectionParams = { // Pointer to ADGameDescription or its superset structure @@ -637,7 +95,11 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NONE + Common::GUIO_NONE, + // Maximum directory depth + 1, + // List of directory globs + 0 }; class TinselMetaEngine : public AdvancedMetaEngine { diff --git a/engines/tinsel/detection_tables.h b/engines/tinsel/detection_tables.h new file mode 100644 index 0000000000..b467cc613e --- /dev/null +++ b/engines/tinsel/detection_tables.h @@ -0,0 +1,567 @@ +/* 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$ + * + */ + +namespace Tinsel { + +using Common::GUIO_NONE; +using Common::GUIO_NOSPEECH; +using Common::GUIO_NOSFX; +using Common::GUIO_NOMUSIC; + +static const TinselGameDescription gameDescriptions[] = { + + // Note: The following is the (hopefully) definitive list of version details: + // TINSEL_V0: Used only by the Discworld 1 demo - this used a more primitive version + // of the Tinsel engine and graphics compression + // TINSEL_V1: There were two versions of the Discworld 1 game - the first used .GRA + // files, and the second used .SCN files. The second also provided some fixes to + // various script bugs and coding errors, but is still considered TINSEL_V1, + // as both game versions work equally well with the newer code. + // TINSEL_V2: The Discworld 2 game used this updated version of the Tinsel 1 engine, + // and as far as we know there aren't any variations of this engine. + + { // Floppy Demo V0 from http://www.adventure-treff.de/specials/dl_demos.php + { + "dw", + "Floppy Demo", + AD_ENTRY1s("dw.gra", "ce1b57761ba705221bcf70955b827b97", 441192), + //AD_ENTRY1s("dw.scn", "ccd72f02183d0e96b6e7d8df9492cda8", 23308), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DEMO, + GUIO_NOSPEECH | GUIO_NOSFX | GUIO_NOMUSIC + }, + GID_DW1, + 0, + GF_DEMO, + TINSEL_V0, + }, + + { // CD Demo V1 version, with *.gra files + { + "dw", + "CD Demo", + { + {"dw.gra", 0, "ef5a2518c9e205f786f5a4526396e661", 781676}, + {"english.smp", 0, NULL, -1}, + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DEMO, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD, + TINSEL_V1, + }, + + { // Multilingual Floppy V1 with *.gra files. + // Note: It contains no english subtitles. + { + "dw", + "Floppy", + { + {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, + {"french.txt", 0, NULL, -1}, + {"german.txt", 0, NULL, -1}, + {"italian.txt", 0, NULL, -1}, + {"spanish.txt", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + GUIO_NOSPEECH + }, + GID_DW1, + 0, + GF_FLOPPY | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // Floppy V1 version, with *.gra files + { + "dw", + "Floppy", + AD_ENTRY1s("dw.gra", "c8808ccd988d603dd35dff42013ae7fd", 781656), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + GID_DW1, + 0, + GF_FLOPPY | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // CD V1 version, with *.gra files (same as the floppy one, with english.smp) + { + "dw", + "CD", + { + {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, + {"english.smp", 0, NULL, -1}, + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // Italian CD with english speech and *.gra files. + // Note: It contains only italian subtitles, but inside english.txt + { + "dw", + "CD", + { + {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, + {"english.txt", 0, "15f0703f85477d7fab4280bf938b61c1", 237774}, + {"english.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::IT_ITA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // Multilingual CD with english speech and *.gra files. + // Note: It contains no english subtitles. + { + "dw", + "CD", + { + {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, + {"english.smp", 0, NULL, -1}, + {"french.txt", 0, NULL, -1}, + {"german.txt", 0, NULL, -1}, + {"italian.txt", 0, NULL, -1}, + {"spanish.txt", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { + { + "dw", + "CD", + { + {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, + {"english.smp", 0, NULL, -1}, + {"french.txt", 0, NULL, -1}, + {"german.txt", 0, NULL, -1}, + {"italian.txt", 0, NULL, -1}, + {"spanish.txt", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + { + { + "dw", + "CD", + { + {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, + {"english.smp", 0, NULL, -1}, + {"french.txt", 0, NULL, -1}, + {"german.txt", 0, NULL, -1}, + {"italian.txt", 0, NULL, -1}, + {"spanish.txt", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::IT_ITA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + { + { + "dw", + "CD", + { + {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, + {"english.smp", 0, NULL, -1}, + {"french.txt", 0, NULL, -1}, + {"german.txt", 0, NULL, -1}, + {"italian.txt", 0, NULL, -1}, + {"spanish.txt", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::ES_ESP, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // English CD v2 + { + "dw", + "CD", + { + {"dw.scn", 0, "70955425870c7720d6eebed903b2ef41", 776188}, + {"english.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // Hebrew CD v2 + { + "dw", + "CD", + { + {"dw.scn", 0, "759d1374b4f02af6d52fc07c96679936", 770780}, + {"english.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::HE_ISR, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // Discworld PSX CD + { + "dw", + "CD", + { + {"english.txt", 0, "7526cfc3a64e00f223795de476b4e2c9", 230326}, + {NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformPSX, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // multilanguage PSX demo + { + "dw", + "CD demo", + { + {"french.txt", 0, "e7020d35f58d0d187052ac406d86cc87", 273914}, + {"german.txt", 0, "52f0a01e0ff0d340b02a36fd5109d705", 263942}, + {"italian.txt", 0, "15f0703f85477d7fab4280bf938b61c1", 239834}, + {"spanish.txt", 0, "c324170c3f1922c605c5cc09ba265aa5", 236702}, + {"english.txt", 0, "7526cfc3a64e00f223795de476b4e2c9", 230326}, + {NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformPSX, + ADGF_DEMO, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_SCNFILES, + TINSEL_V1, + }, + +#if 0 + { // English Saturn CD + { + "dw", + "CD", + { + {"dw.scn", 0, "6803f293c88758057cc685b9437f7637", 382248}, + {"english.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, +#endif + +#if 0 + { // Mac multilanguage CD + { + "dw", + "CD", + { + {"dw.scn", 0, "cfc40a8d5d476a1c9d3abf826fa46f8c", 1265532}, + {"english.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + +#endif + + { // German CD re-release "Neon Edition" + // Note: This release has ENGLISH.TXT (with german content) instead of GERMAN.TXT + { + "dw", + "CD", + AD_ENTRY1s("dw.scn", "6182c7986eaec893c62fb6ea13a9f225", 774556), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // Russian Discworld 1 + { + "dw", + "CD", + { + {"dw.scn", 0, "133041bde59d05c1bf084fd6f1bdce4b", 776524}, + {"english.txt", 0, "f73dcbd7b136b37c2adf7c9448ea336d", 231821}, + {"english.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::RU_RUS, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // European/Australian Discworld 2 release + { + "dw2", + "CD", + { + {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, + {"english1.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::EN_GRB, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW2, + 0, + GF_CD | GF_SCNFILES, + TINSEL_V2, + }, + + { // US Discworld 2 release + { + "dw2", + "CD", + { + {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, + {"us1.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::EN_USA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW2, + 0, + GF_CD | GF_SCNFILES, + TINSEL_V2, + }, + + { // French version of Discworld 2 + { + "dw2", + "CD", + { + {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, + {"french1.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::FR_FRA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW2, + 0, + GF_CD | GF_SCNFILES, + TINSEL_V2, + }, + + { // German Discworld 2 re-release "Neon Edition" + { + "dw2", + "CD", + { + {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, + {"german1.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW2, + 0, + GF_CD | GF_SCNFILES, + TINSEL_V2, + }, + + { // Italian/Spanish Discworld 2 + { + "dw2", + "CD", + { + {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, + {"english1.smp", 0, NULL, -1}, + {"italian1.txt", 0, "d443249f8b55489b5888c227b9096f4e", 246495}, + {NULL, 0, NULL, 0} + }, + Common::IT_ITA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW2, + 0, + GF_CD | GF_SCNFILES, + TINSEL_V2, + }, + { + { + "dw2", + "CD", + { + {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, + {"english1.smp", 0, NULL, -1}, + {"spanish1.txt", 0, "bc6e147c5f542db228ac577357e4d897", 230323}, + {NULL, 0, NULL, 0} + }, + Common::ES_ESP, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW2, + 0, + GF_CD | GF_SCNFILES, + TINSEL_V2, + }, + + { // Russian Discworld 2 release by Fargus + { + "dw2", + "CD", + { + {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, + {"english1.smp", 0, NULL, -1}, + {"english1.txt", 0, "b522e19d7b2cd7b85e50e36fe48e36a9", 274444}, + {NULL, 0, NULL, 0} + }, + Common::RU_RUS, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW2, + 0, + GF_CD | GF_SCNFILES, + TINSEL_V2, + }, + + { AD_TABLE_END_MARKER, 0, 0, 0, 0 } +}; + +} // End of namespace Tinsel diff --git a/engines/tinsel/graphics.cpp b/engines/tinsel/graphics.cpp index 9700e8947f..48270d94e3 100644 --- a/engines/tinsel/graphics.cpp +++ b/engines/tinsel/graphics.cpp @@ -443,6 +443,12 @@ static void t2WrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool apply int numBytes; int clipAmount; + // WORKAROUND: One of the mortician frames has several corrupt bytes in the Russian version + if ((pObj->hBits == 2517583660UL) && (_vm->getLanguage() == Common::RU_RUS)) { + uint8 correctBytes[5] = {0xA3, 0x00, 0x89, 0xC0, 0xA6}; + Common::copy(&correctBytes[0], &correctBytes[5], srcP); + } + for (int y = 0; y < pObj->height; ++y) { // Get the position to start writing out from uint8 *tempP = !horizFlipped ? destP : @@ -596,6 +602,23 @@ static void PackedWrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, int numBytes, colour; int v; + if (_vm->getLanguage() == Common::RU_RUS) { + // WORKAROUND: One of the mortician frames has several corrupt bytes in the Russian version + if (pObj->hBits == 2517583393UL) { + uint8 correctBytes[5] = {0x00, 0x00, 0x17, 0x01, 0x00}; + Common::copy(&correctBytes[0], &correctBytes[5], srcP + 267); + } + // WORKAROUND: One of Dibbler's frames in the end sequence has corrupt bytes in the Russian version + if (pObj->hBits == 33651742) { + uint8 correctBytes[40] = { + 0x06, 0xc0, 0xd6, 0xc1, 0x09, 0xce, 0x0d, 0x24, 0x02, 0x12, 0x01, 0x00, 0x00, 0x23, 0x21, 0x32, + 0x12, 0x00, 0x00, 0x20, 0x01, 0x11, 0x32, 0x12, 0x01, 0x00, 0x00, 0x1b, 0x02, 0x11, 0x34, 0x11, + 0x00, 0x00, 0x18, 0x01, 0x11, 0x35, 0x21, 0x01 + }; + Common::copy(&correctBytes[0], &correctBytes[40], srcP); + } + } + if (applyClipping) { pObj->height -= pObj->botClip; topClip = pObj->topClip; diff --git a/engines/tinsel/pcode.cpp b/engines/tinsel/pcode.cpp index c472a770d2..98fb078459 100644 --- a/engines/tinsel/pcode.cpp +++ b/engines/tinsel/pcode.cpp @@ -148,6 +148,7 @@ static const byte fragment12[] = {OP_JMPTRUE | OPSIZE16, FRAGMENT_WORD(1491), OP_ONE, OP_LIBCALL | OPSIZE8, 14, // Re-show the cursor OP_IMM | OPSIZE16, FRAGMENT_WORD(322), OP_LIBCALL | OPSIZE8, 46, // Give back the whistle OP_JUMP | OPSIZE16, FRAGMENT_WORD(1568)}; +static const byte fragment13[] = {OP_ZERO, OP_GSTORE | OPSIZE16, FRAGMENT_WORD(306)}; #undef FRAGMENT_WORD @@ -207,6 +208,12 @@ const WorkaroundEntry workaroundList[] = { // See bug report #2934211. {TINSEL_V1, true, 352601285, 1569, sizeof(fragment11), fragment11}, {TINSEL_V1, false, 352602304, 1488, sizeof(fragment12), fragment12}, + + // DW2: Corrects a bug with global 306 not being cleared if you leave + // the marketplace scene whilst D'Blah is talking (even if it's not + // actually audible); returning to the scene and clicking on him multiple + // times would cause the game to crash + {TINSEL_V2, true, 1109294728, 0, sizeof(fragment13), fragment13}, {TINSEL_V0, false, 0, 0, 0, NULL} }; diff --git a/engines/tinsel/tinlib.cpp b/engines/tinsel/tinlib.cpp index 677392a35d..766d4ed54a 100644 --- a/engines/tinsel/tinlib.cpp +++ b/engines/tinsel/tinlib.cpp @@ -5557,7 +5557,7 @@ int CallLibraryRoutine(CORO_PARAM, int operand, int32 *pp, const INT_CONTEXT *pi case WALKED: { // Common to both DW1 & DW2 pp -= 3; // 4 parameters - bool tmp; + bool tmp = false; Walked(coroParam, pp[0], pp[1], pp[2], pp[3], pic->escOn, pic->myEscape, tmp); if (!coroParam) { // Only write the result to the stack if walked actually completed running. diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp index 4335b51818..3a4191227a 100644 --- a/engines/tinsel/tinsel.cpp +++ b/engines/tinsel/tinsel.cpp @@ -855,11 +855,11 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc) if (cd_num >= 0) _system->getAudioCDManager()->openCD(cd_num); - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); - //bool adlib = (midiDriver == MD_ADLIB); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); + bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); + //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB); - _driver = MidiDriver::createMidi(midiDriver); + _driver = MidiDriver::createMidi(dev); if (native_mt32) _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); diff --git a/engines/tinsel/tinsel.h b/engines/tinsel/tinsel.h index 0e1d705815..df27a1e0e1 100644 --- a/engines/tinsel/tinsel.h +++ b/engines/tinsel/tinsel.h @@ -61,6 +61,8 @@ class PCMMusicPlayer; class Scheduler; class SoundManager; +typedef Common::List<Common::Rect> RectList; + enum TinselGameID { GID_DW1 = 0, GID_DW2 = 1 @@ -203,6 +205,10 @@ public: /** Stack of pending keypresses. */ Common::List<Common::Event> _keypresses; + + /** List of all clip rectangles. */ + RectList _clipRects; + private: //MidiMusicPlayer *_midiMusic; int _musicVolume; diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp index 65a6a29bcc..35f03fa657 100644 --- a/engines/touche/detection.cpp +++ b/engines/touche/detection.cpp @@ -124,6 +124,11 @@ static const ADFileBasedFallback fileBasedFallback[] = { } // End of namespace Touche +static const char *directoryGlobs[] = { + "database", + 0 +}; + static const ADParams detectionParams = { (const byte *)Touche::gameDescriptions, sizeof(ADGameDescription), @@ -134,7 +139,11 @@ static const ADParams detectionParams = { Touche::fileBasedFallback, // file-based detection data to enable not yet known versions to start kADFlagPrintWarningOnFileBasedFallback, // Additional GUI options (for every game} - Common::GUIO_NONE + Common::GUIO_NONE, + // Maximum directory depth + 2, + // List of directory globs + directoryGlobs }; class ToucheMetaEngine : public AdvancedMetaEngine { diff --git a/engines/touche/midi.cpp b/engines/touche/midi.cpp index 9dbef4d76f..439d3b9ac2 100644 --- a/engines/touche/midi.cpp +++ b/engines/touche/midi.cpp @@ -92,9 +92,9 @@ void MidiPlayer::setVolume(int volume) { } int MidiPlayer::open() { - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - _nativeMT32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); - _driver = MidiDriver::createMidi(midiDriver); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); + _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); + _driver = MidiDriver::createMidi(dev); int ret = _driver->open(); if (ret == 0) { _parser = MidiParser::createParser_SMF(); diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp index 187e685d06..2dc8b76b4f 100644 --- a/engines/touche/touche.cpp +++ b/engines/touche/touche.cpp @@ -28,6 +28,8 @@ #include "common/debug-channels.h" #include "common/events.h" #include "common/EventRecorder.h" +#include "common/file.h" +#include "common/fs.h" #include "common/system.h" #include "engines/util.h" @@ -70,6 +72,10 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language) _menuRedrawCounter = 0; memset(_paletteBuffer, 0, sizeof(_paletteBuffer)); + const Common::FSNode gameDataDir(ConfMan.get("path")); + + SearchMan.addSubDirectoryMatching(gameDataDir, "database"); + DebugMan.addDebugChannel(kDebugEngine, "Engine", "Engine debug level"); DebugMan.addDebugChannel(kDebugGraphics, "Graphics", "Graphics debug level"); DebugMan.addDebugChannel(kDebugResource, "Resource", "Resource debug level"); diff --git a/engines/tucker/detection.cpp b/engines/tucker/detection.cpp index b4f30cb7fd..0a9dec9b46 100644 --- a/engines/tucker/detection.cpp +++ b/engines/tucker/detection.cpp @@ -114,7 +114,9 @@ static const ADParams detectionParams = { "tucker", 0, 0, - Common::GUIO_NONE + Common::GUIO_NONE, + 1, + 0 }; static const ADGameDescription tuckerDemoGameDescription = { diff --git a/graphics/fontman.cpp b/graphics/fontman.cpp index 1827cb69aa..c6972cfaab 100644 --- a/graphics/fontman.cpp +++ b/graphics/fontman.cpp @@ -57,7 +57,29 @@ FontManager::~FontManager() { g_consolefont = 0; } +const struct { + const char *name; + FontManager::FontUsage id; +} builtinFontNames[] = { + { "builtinOSD", FontManager::kOSDFont }, + { "builtinConsole", FontManager::kConsoleFont }, + { "fixed5x8.bdf", FontManager::kConsoleFont }, + { "fixed5x8-iso-8859-1.bdf", FontManager::kConsoleFont }, + { "fixed5x8-ascii.bdf", FontManager::kConsoleFont }, + { "clR6x12.bdf", FontManager::kGUIFont }, + { "clR6x12-iso-8859-1.bdf", FontManager::kGUIFont }, + { "clR6x12-ascii.bdf", FontManager::kGUIFont }, + { "helvB12.bdf", FontManager::kBigGUIFont }, + { "helvB12-iso-8859-1.bdf", FontManager::kBigGUIFont }, + { "helvB12-ascii.bdf", FontManager::kBigGUIFont }, + { 0, FontManager::kOSDFont } +}; + const Font *FontManager::getFontByName(const Common::String &name) const { + for (int i = 0; builtinFontNames[i].name; i++) + if (!scumm_stricmp(name.c_str(), builtinFontNames[i].name)) + return getFontByUsage(builtinFontNames[i].id); + if (!_fontMap.contains(name)) return 0; return _fontMap[name]; diff --git a/graphics/fontman.h b/graphics/fontman.h index 9896fad38c..7871f32ba9 100644 --- a/graphics/fontman.h +++ b/graphics/fontman.h @@ -38,10 +38,10 @@ namespace Graphics { class FontManager : public Common::Singleton<FontManager> { public: enum FontUsage { - kOSDFont, - kConsoleFont, - kGUIFont, - kBigGUIFont + kOSDFont = 0, + kConsoleFont = 1, + kGUIFont = 2, + kBigGUIFont = 3 }; /** diff --git a/graphics/scaler.h b/graphics/scaler.h index 22bda5273a..577a91ccc1 100644 --- a/graphics/scaler.h +++ b/graphics/scaler.h @@ -77,7 +77,7 @@ enum { * Creates a thumbnail from the current screen (without overlay). * * @param surf a surface (will always have 16 bpp after this for now) - * @return false if a error occured + * @return false if a error occurred */ extern bool createThumbnailFromScreen(Graphics::Surface *surf); diff --git a/graphics/scaler/thumbnail_intern.cpp b/graphics/scaler/thumbnail_intern.cpp index 12048249f0..f767c91bd5 100644 --- a/graphics/scaler/thumbnail_intern.cpp +++ b/graphics/scaler/thumbnail_intern.cpp @@ -148,8 +148,8 @@ static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) { Graphics::Surface newscreen; newscreen.create(width, in.h, in.bytesPerPixel); - uint8 *dst = (uint8*)newscreen.getBasePtr((320 - in.w) / 2, 0); - const uint8 *src = (uint8*)in.getBasePtr(0, 0); + uint8 *dst = (uint8 *)newscreen.getBasePtr((320 - in.w) / 2, 0); + const uint8 *src = (const uint8 *)in.getBasePtr(0, 0); uint16 height = in.h; while (height--) { @@ -173,8 +173,8 @@ static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) { Graphics::Surface newscreen; newscreen.create(width, 400, in.bytesPerPixel); - uint8 *dst = (uint8*)in.getBasePtr(0, (400 - 240) / 2); - const uint8 *src = (uint8*)in.getBasePtr(41, 28); + uint8 *dst = (uint8 *)newscreen.getBasePtr(0, (400 - 240) / 2); + const uint8 *src = (const uint8 *)in.getBasePtr(41, 28); for (int y = 0; y < 240; ++y) { memcpy(dst, src, 640 * in.bytesPerPixel); @@ -184,6 +184,18 @@ static bool createThumbnail(Graphics::Surface &out, Graphics::Surface &in) { in.free(); in = newscreen; + } else if (width == 640 && inHeight == 440) { + // Special case to handle KQ6 Windows: resize the screen to 640x480, + // adding a black band in the bottom. + inHeight = 480; + + Graphics::Surface newscreen; + newscreen.create(width, 480, in.bytesPerPixel); + + memcpy(newscreen.getBasePtr(0, 0), in.getBasePtr(0, 0), width * 440 * in.bytesPerPixel); + + in.free(); + in = newscreen; } uint16 newHeight = !(inHeight % 240) ? kThumbnailHeight2 : kThumbnailHeight1; diff --git a/graphics/video/codecs/qdm2.cpp b/graphics/video/codecs/qdm2.cpp index e12be21303..9f151b4ba8 100644 --- a/graphics/video/codecs/qdm2.cpp +++ b/graphics/video/codecs/qdm2.cpp @@ -157,7 +157,7 @@ public: ~QDM2Stream(); bool isStereo() const { return _channels == 2; } - bool endOfData() const { return ((_stream->pos() == _stream->size()) && (_outputSamples.size() == 0)); } + bool endOfData() const { return _stream->pos() >= _stream->size() && _outputSamples.size() == 0 && _subPacket == 0; } int getRate() const { return _sampleRate; } int readBuffer(int16 *buffer, const int numSamples); @@ -199,7 +199,7 @@ private: int _fftCoefsMinIndex[5]; int _fftCoefsMaxIndex[5]; int _fftLevelExp[6]; - //RDFTContext _rdftCtx; + RDFTContext _rdftCtx; QDM2FFT _fft; // I/O data @@ -230,6 +230,7 @@ private: int _doSynthFilter; // used to perform or skip synthesis filter uint8 _subPacket; // 0 to 15 + uint32 _superBlockStart; int _noiseIdx; // index for dithering noise table byte _emptyBuffer[FF_INPUT_BUFFER_PADDING_SIZE]; @@ -261,8 +262,6 @@ private: float _noiseSamples[128]; void initNoiseSamples(void); - RDFTContext _rdftCtx; - void average_quantized_coeffs(void); void build_sb_samples_from_noise(int sb); void fix_coding_method_array(int sb, int channels, sb_int8_array coding_method); @@ -331,8 +330,6 @@ static inline int scummvm_log2(int n) { static inline void initGetBits(GetBitContext *s, const uint8 *buffer, int bitSize) { int bufferSize = (bitSize + 7) >> 3; - debug(1, "void initGetBits(GetBitContext *s, const uint8 *buffer, int bitSize)"); - if (bufferSize < 0 || bitSize < 0) { bufferSize = bitSize = 0; buffer = NULL; @@ -345,7 +342,6 @@ static inline void initGetBits(GetBitContext *s, const uint8 *buffer, int bitSiz } static inline int getBitsCount(GetBitContext *s) { - debug(1, "int getBitsCount(GetBitContext *s)"); return s->index; } @@ -353,13 +349,9 @@ static inline unsigned int getBits1(GetBitContext *s) { int index; uint8 result; - debug(1, "unsigned int getBits1(GetBitContext *s)"); - index = s->index; result = s->buffer[index >> 3]; - debug(1, "index : %d", index); - result >>= (index & 0x07); result &= 1; index++; @@ -371,12 +363,8 @@ static inline unsigned int getBits1(GetBitContext *s) { static inline unsigned int getBits(GetBitContext *s, int n) { int tmp, reCache, reIndex; - debug(1, "unsigned int getBits(GetBitContext *s, int n)"); - reIndex = s->index; - debug(1, "reIndex : %d", reIndex); - reCache = READ_LE_UINT32((const uint8 *)s->buffer + (reIndex >> 3)) >> (reIndex & 0x07); tmp = (reCache) & ((uint32)0xffffffff >> (32 - n)); @@ -389,13 +377,9 @@ static inline unsigned int getBits(GetBitContext *s, int n) { static inline void skipBits(GetBitContext *s, int n) { int reIndex, reCache; - debug(1, "void skipBits(GetBitContext *s, int n)"); - reIndex = s->index; reCache = 0; - debug(1, "reIndex : %d", reIndex); - reCache = READ_LE_UINT32((const uint8 *)s->buffer + (reIndex >> 3)) >> (reIndex & 0x07); s->index = reIndex + n; } @@ -1331,20 +1315,12 @@ static int getVlc2(GetBitContext *s, int16 (*table)[2], int bits, int maxDepth) int code; int n; - debug(1, "int getVlc2(GetBitContext *s, int16 (*table)[2], int bits, int maxDepth)"); - reIndex = s->index; reCache = READ_LE_UINT32(s->buffer + (reIndex >> 3)) >> (reIndex & 0x07); index = reCache & (0xffffffff >> (32 - bits)); code = table[index][0]; n = table[index][1]; - debug(1, "reIndex : %d", reIndex); - debug(1, "reCache : %d", reCache); - debug(1, "index : %d", index); - debug(1, "code : %d", code); - debug(1, "n : %d", n); - if (maxDepth > 1 && n < 0){ reIndex += bits; reCache = READ_LE_UINT32(s->buffer + (reIndex >> 3)) >> (reIndex & 0x07); @@ -1416,7 +1392,6 @@ static int build_table(VLC *vlc, int table_nb_bits, table_size = 1 << table_nb_bits; table_index = allocTable(vlc, table_size, flags & 4); - debug(2, "QDM2 new table index=%d size=%d code_prefix=%x n=%d", table_index, table_size, code_prefix, n_prefix); if (table_index < 0) return -1; table = &vlc->table[table_index]; @@ -1437,7 +1412,6 @@ static int build_table(VLC *vlc, int table_nb_bits, symbol = i; else GET_DATA(symbol, symbols, i, symbols_wrap, symbols_size); - debug(2, "QDM2 i=%d n=%d code=0x%x", i, n, code); // if code matches the prefix, it is in the table n -= n_prefix; if(flags & 2) @@ -1452,7 +1426,6 @@ static int build_table(VLC *vlc, int table_nb_bits, for(k = 0; k < nb; k++) { if(flags & 2) j = (code >> n_prefix) + (k<<n); - debug(2, "QDM2 %4x: code=%d n=%d",j, i, n); if (table[j][1] /*bits*/ != 0) { error("QDM2 incorrect codes"); return -1; @@ -1464,7 +1437,6 @@ static int build_table(VLC *vlc, int table_nb_bits, } else { n -= table_nb_bits; j = (code >> ((flags & 2) ? n_prefix : n)) & ((1 << table_nb_bits) - 1); - debug(2, "QDM2 %4x: n=%d (subtable)", j, n); // compute table size n1 = -table[j][1]; //bits if (n > n1) @@ -1537,8 +1509,6 @@ void initVlcSparse(VLC *vlc, int nb_bits, int nb_codes, error("called on a partially initialized table"); } - debug(2, "QDM2 build table nb_codes=%d", nb_codes); - if (build_table(vlc, nb_bits, nb_codes, bits, bits_wrap, bits_size, codes, codes_wrap, codes_size, @@ -1754,6 +1724,7 @@ QDM2Stream::QDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadS _stream = stream; _compressedData = NULL; _subPacket = 0; + _superBlockStart = 0; memset(_quantizedCoeffs, 0, sizeof(_quantizedCoeffs)); memset(_fftLevelExp, 0, sizeof(_fftLevelExp)); _noiseIdx = 0; @@ -2015,8 +1986,6 @@ static void qdm2_decode_sub_packet_header(GetBitContext *gb, QDM2SubPacket *sub_ sub_packet->data = &gb->buffer[getBitsCount(gb) / 8]; // FIXME: this depends on bitreader internal data } - - debug(1, "QDM2 Subpacket: type=%d size=%d start_offs=%x", sub_packet->type, sub_packet->size, getBitsCount(gb) / 8); } /** @@ -2881,7 +2850,6 @@ void QDM2Stream::qdm2_fft_init_coefficient(int sub_packet, int offset, int durat } void QDM2Stream::qdm2_fft_decode_tones(int duration, GetBitContext *gb, int b) { - debug(1, "QDM2Stream::qdm2_fft_decode_tones() duration: %d b:%d", duration, b); int channel, stereo, phase, exp; int local_int_4, local_int_8, stereo_phase, local_int_10; int local_int_14, stereo_exp, local_int_20, local_int_28; @@ -2896,9 +2864,7 @@ void QDM2Stream::qdm2_fft_decode_tones(int duration, GetBitContext *gb, int b) { while (1) { if (_superblocktype_2_3) { - debug(1, "QDM2Stream::qdm2_fft_decode_tones() local_int_8: %d", local_int_8); while ((n = qdm2_get_vlc(gb, &_vlcTabFftToneOffset[local_int_8], 1, 2)) < 2) { - debug(1, "QDM2Stream::qdm2_fft_decode_tones() local_int_8: %d", local_int_8); offset = 1; if (n == 0) { local_int_4 += local_int_10; @@ -2959,7 +2925,6 @@ void QDM2Stream::qdm2_fft_decode_tones(int duration, GetBitContext *gb, int b) { } void QDM2Stream::qdm2_decode_fft_packets(void) { - debug(1, "QDM2Stream::qdm2_decode_fft_packets()"); int i, j, min, max, value, type, unknown_flag; GetBitContext gb; @@ -2994,7 +2959,6 @@ void QDM2Stream::qdm2_decode_fft_packets(void) { return; // decode FFT tones - debug(1, "QDM2Stream::qdm2_decode_fft_packets initGetBits() packet->size*8: %d", packet->size*8); initGetBits(&gb, packet->data, packet->size*8); if (packet->type >= 32 && packet->type < 48 && !fft_subpackets[packet->type - 16]) @@ -3008,19 +2972,16 @@ void QDM2Stream::qdm2_decode_fft_packets(void) { int duration = _subSampling + 5 - (type & 15); if (duration >= 0 && duration < 4) { // TODO: Should be <= 4? - debug(1, "QDM2Stream::qdm2_decode_fft_packets qdm2_fft_decode_tones() #1"); qdm2_fft_decode_tones(duration, &gb, unknown_flag); } } else if (type == 31) { for (j=0; j < 4; j++) { - debug(1, "QDM2Stream::qdm2_decode_fft_packets qdm2_fft_decode_tones() #2"); qdm2_fft_decode_tones(j, &gb, unknown_flag); } } else if (type == 46) { for (j=0; j < 6; j++) _fftLevelExp[j] = getBits(&gb, 6); for (j=0; j < 4; j++) { - debug(1, "QDM2Stream::qdm2_decode_fft_packets qdm2_fft_decode_tones() #3"); qdm2_fft_decode_tones(j, &gb, unknown_flag); } } @@ -3151,16 +3112,12 @@ void QDM2Stream::qdm2_fft_tone_synthesizer(uint8 sub_packet) { } void QDM2Stream::qdm2_calculate_fft(int channel) { - debug(1, "QDM2Stream::qdm2_calculate_fft channel: %d", channel); const float gain = (_channels == 1 && _channels == 2) ? 0.5f : 1.0f; int i; _fft.complex[channel][0].re *= 2.0f; _fft.complex[channel][0].im = 0.0f; - //debug(1, "QDM2Stream::qdm2_calculate_fft _fft.complex[channel][0].re: %lf", _fft.complex[channel][0].re); - //debug(1, "QDM2Stream::qdm2_calculate_fft _fft.complex[channel][0].im: %lf", _fft.complex[channel][0].im); - rdftCalc(&_rdftCtx, (float *)_fft.complex[channel]); // add samples to output buffer @@ -3209,82 +3166,80 @@ int QDM2Stream::qdm2_decodeFrame(Common::SeekableReadStream *in) { int ch, i; const int frame_size = (_sFrameSize * _channels); + // If we're in any packet but the first, seek back to the first + if (_subPacket == 0) + _superBlockStart = in->pos(); + else + in->seek(_superBlockStart); + // select input buffer - if(in->eos() || in->size() == in->pos()) { + if (in->eos() || in->pos() >= in->size()) { debug(1, "QDM2Stream::qdm2_decodeFrame End of Input Stream"); return 0; } - if((in->size() - in->pos()) < _packetSize) { + + if ((in->size() - in->pos()) < _packetSize) { debug(1, "QDM2Stream::qdm2_decodeFrame Insufficient Packet Data in Input Stream Found: %d Need: %d", in->size() - in->pos(), _packetSize); return 0; } - in->read(_compressedData, _packetSize); - debug(1, "QDM2Stream::qdm2_decodeFrame constructed input data"); + if (!in->eos()) { + in->read(_compressedData, _packetSize); + debug(1, "QDM2Stream::qdm2_decodeFrame constructed input data"); + } // copy old block, clear new block of output samples memmove(_outputBuffer, &_outputBuffer[frame_size], frame_size * sizeof(float)); memset(&_outputBuffer[frame_size], 0, frame_size * sizeof(float)); debug(1, "QDM2Stream::qdm2_decodeFrame cleared outputBuffer"); - // decode block of QDM2 compressed data - debug(1, "QDM2Stream::qdm2_decodeFrame decode block of QDM2 compressed data"); - if (_subPacket == 0) { - _hasErrors = false; // reset it for a new super block - debug(1, "QDM2 : Superblock follows"); - qdm2_decode_super_block(); - } - - // parse subpackets - debug(1, "QDM2Stream::qdm2_decodeFrame parse subpackets"); - if (!_hasErrors) { - if (_subPacket == 2) { - debug(1, "QDM2Stream::qdm2_decodeFrame qdm2_decode_fft_packets()"); - qdm2_decode_fft_packets(); + if (!in->eos()) { + // decode block of QDM2 compressed data + debug(1, "QDM2Stream::qdm2_decodeFrame decode block of QDM2 compressed data"); + if (_subPacket == 0) { + _hasErrors = false; // reset it for a new super block + debug(1, "QDM2 : Superblock follows"); + qdm2_decode_super_block(); } - debug(1, "QDM2Stream::qdm2_decodeFrame qdm2_fft_tone_synthesizer(%d)", _subPacket); - qdm2_fft_tone_synthesizer(_subPacket); - } - - // sound synthesis stage 1 (FFT) - debug(1, "QDM2Stream::qdm2_decodeFrame sound synthesis stage 1 (FFT)"); - for (ch = 0; ch < _channels; ch++) { - qdm2_calculate_fft(ch); + // parse subpackets + debug(1, "QDM2Stream::qdm2_decodeFrame parse subpackets"); + if (!_hasErrors) { + if (_subPacket == 2) { + debug(1, "QDM2Stream::qdm2_decodeFrame qdm2_decode_fft_packets()"); + qdm2_decode_fft_packets(); + } - if (!_hasErrors && _subPacketListC[0].packet != NULL) { - error("QDM2 : has errors, and C list is not empty"); - return 0; + debug(1, "QDM2Stream::qdm2_decodeFrame qdm2_fft_tone_synthesizer(%d)", _subPacket); + qdm2_fft_tone_synthesizer(_subPacket); } - } - // sound synthesis stage 2 (MPEG audio like synthesis filter) - debug(1, "QDM2Stream::qdm2_decodeFrame sound synthesis stage 2 (MPEG audio like synthesis filter)"); - if (!_hasErrors && _doSynthFilter) - qdm2_synthesis_filter(_subPacket); + // sound synthesis stage 1 (FFT) + debug(1, "QDM2Stream::qdm2_decodeFrame sound synthesis stage 1 (FFT)"); + for (ch = 0; ch < _channels; ch++) { + qdm2_calculate_fft(ch); - _subPacket = (_subPacket + 1) % 16; + if (!_hasErrors && _subPacketListC[0].packet != NULL) { + error("QDM2 : has errors, and C list is not empty"); + return 0; + } + } - if(_hasErrors) - warning("QDM2 Packet error..."); + // sound synthesis stage 2 (MPEG audio like synthesis filter) + debug(1, "QDM2Stream::qdm2_decodeFrame sound synthesis stage 2 (MPEG audio like synthesis filter)"); + if (!_hasErrors && _doSynthFilter) + qdm2_synthesis_filter(_subPacket); - // clip and convert output float[] to 16bit signed samples - debug(1, "QDM2Stream::qdm2_decodeFrame clip and convert output float[] to 16bit signed samples"); + _subPacket = (_subPacket + 1) % 16; -/* - debugN(1, "Input Data Packet:"); - for(i = 0; i < _packetSize; i++) { - debugN(1, " %d", _compressedData[i]); - } - debugN(1, " Output Data Packet:"); - for(i = 0; i < frame_size; i++) { - debugN(1, " %d", (int)_outputBuffer[i]); + if(_hasErrors) + warning("QDM2 Packet error..."); + + // clip and convert output float[] to 16bit signed samples + debug(1, "QDM2Stream::qdm2_decodeFrame clip and convert output float[] to 16bit signed samples"); } - debug(1, ""); -*/ for (i = 0; i < frame_size; i++) { - //debug(1, "QDM2Stream::qdm2_decodeFrame i: %d", i); int value = (int)_outputBuffer[i]; if (value > SOFTCLIP_THRESHOLD) @@ -3302,17 +3257,17 @@ int QDM2Stream::readBuffer(int16 *buffer, const int numSamples) { int32 decodedSamples = _outputSamples.size(); int32 i; - //while((int)_outputSamples.size() < numSamples) { - while(!_stream->eos() && _stream->pos() != _stream->size()) { + while (decodedSamples < numSamples) { i = qdm2_decodeFrame(_stream); - if(i == 0) + if (i == 0) break; // Out Of Decode Frames... decodedSamples += i; } - if(decodedSamples > numSamples) + + if (decodedSamples > numSamples) decodedSamples = numSamples; - for(i = 0; i < decodedSamples; i++) + for (i = 0; i < decodedSamples; i++) buffer[i] = _outputSamples.remove_at(0); return decodedSamples; diff --git a/graphics/video/codecs/qdm2.h b/graphics/video/codecs/qdm2.h index c9a01a70ee..9eb566d04d 100644 --- a/graphics/video/codecs/qdm2.h +++ b/graphics/video/codecs/qdm2.h @@ -44,7 +44,7 @@ namespace Graphics { * * @param stream the SeekableReadStream from which to read the FLAC data * @param extraData the QuickTime extra data stream - * @return a new AudioStream, or NULL, if an error occured + * @return a new AudioStream, or NULL, if an error occurred */ Audio::AudioStream *makeQDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadStream *extraData); diff --git a/graphics/video/qt_decoder.cpp b/graphics/video/qt_decoder.cpp index 49d2b0aed9..a95243ba6a 100644 --- a/graphics/video/qt_decoder.cpp +++ b/graphics/video/qt_decoder.cpp @@ -191,8 +191,10 @@ Codec *QuickTimeDecoder::createCodec(uint32 codecTag, byte bitsPerPixel) { } void QuickTimeDecoder::startAudio() { - if (_audStream) // No audio/audio not supported + if (_audStream) { // No audio/audio not supported + updateAudioBuffer(); g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_audHandle, _audStream); + } } void QuickTimeDecoder::stopAudio() { @@ -534,6 +536,8 @@ int QuickTimeDecoder::readCMOV(MOVatom atom) { unsigned long dstLen = uncompressedSize; if (!Common::uncompress(uncompressedData, &dstLen, compressedData, compressedSize)) { warning ("Could not uncompress cmov chunk"); + free(compressedData); + free(uncompressedData); return -1; } diff --git a/gui/EditTextWidget.cpp b/gui/EditTextWidget.cpp index 658ac21117..7079453173 100644 --- a/gui/EditTextWidget.cpp +++ b/gui/EditTextWidget.cpp @@ -30,16 +30,16 @@ namespace GUI { -EditTextWidget::EditTextWidget(GuiObject *boss, int x, int y, int w, int h, const String &text, uint32 cmd) - : EditableWidget(boss, x, y - 1, w, h + 2, cmd) { +EditTextWidget::EditTextWidget(GuiObject *boss, int x, int y, int w, int h, const String &text, const char *tooltip, uint32 cmd) + : EditableWidget(boss, x, y - 1, w, h + 2, tooltip, cmd) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_WANT_TICKLE); _type = kEditTextWidget; setEditString(text); } -EditTextWidget::EditTextWidget(GuiObject *boss, const String &name, const String &text, uint32 cmd) - : EditableWidget(boss, name, cmd) { +EditTextWidget::EditTextWidget(GuiObject *boss, const String &name, const String &text, const char *tooltip, uint32 cmd) + : EditableWidget(boss, name, tooltip, cmd) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_WANT_TICKLE); _type = kEditTextWidget; diff --git a/gui/EditTextWidget.h b/gui/EditTextWidget.h index 5a5823cfb1..9c4ef03648 100644 --- a/gui/EditTextWidget.h +++ b/gui/EditTextWidget.h @@ -41,8 +41,8 @@ protected: int _rightPadding; public: - EditTextWidget(GuiObject *boss, int x, int y, int w, int h, const String &text, uint32 cmd = 0); - EditTextWidget(GuiObject *boss, const String &name, const String &text, uint32 cmd = 0); + EditTextWidget(GuiObject *boss, int x, int y, int w, int h, const String &text, const char *tooltip = 0, uint32 cmd = 0); + EditTextWidget(GuiObject *boss, const String &name, const String &text, const char *tooltp = 0, uint32 cmd = 0); void setEditString(const String &str); diff --git a/gui/GuiManager.cpp b/gui/GuiManager.cpp index 99fb3be4dc..ff747c6e92 100644 --- a/gui/GuiManager.cpp +++ b/gui/GuiManager.cpp @@ -27,6 +27,8 @@ #include "common/util.h" #include "common/config-manager.h" #include "common/algorithm.h" +#include "common/timer.h" +#include "common/translation.h" #include "backends/keymapper/keymapper.h" @@ -48,7 +50,7 @@ enum { // Constructor GuiManager::GuiManager() : _redrawStatus(kRedrawDisabled), - _stateIsSaved(false), _cursorAnimateCounter(0), _cursorAnimateTimer(0) { + _stateIsSaved(false), _cursorAnimateCounter(0), _cursorAnimateTimer(0) { _theme = 0; _useStdCursor = false; @@ -74,10 +76,13 @@ GuiManager::GuiManager() : _redrawStatus(kRedrawDisabled), error("Failed to load any GUI theme, aborting"); } } + + _tooltip = new Tooltip(this); } GuiManager::~GuiManager() { delete _theme; + delete _tooltip; } #ifdef ENABLE_KEYMAPPER @@ -94,27 +99,28 @@ void GuiManager::initKeymap() { Action *act; Keymap *guiMap = new Keymap("gui"); - act = new Action(guiMap, "CLOS", "Close", kGenericActionType, kStartKeyType); + act = new Action(guiMap, "CLOS", _("Close"), kGenericActionType, kStartKeyType); act->addKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE, 0)); - act = new Action(guiMap, "CLIK", "Mouse click"); + act = new Action(guiMap, "CLIK", _("Mouse click")); act->addLeftClickEvent(); - act = new Action(guiMap, "VIRT", "Display keyboard", kVirtualKeyboardActionType); + act = new Action(guiMap, "VIRT", _("Display keyboard"), kVirtualKeyboardActionType); act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0)); - act = new Action(guiMap, "REMP", "Remap keys", kKeyRemapActionType); + act = new Action(guiMap, "REMP", _("Remap keys"), kKeyRemapActionType); act->addKeyEvent(KeyState(KEYCODE_F8, ASCII_F8, 0)); mapper->addGlobalKeymap(guiMap); } #endif -bool GuiManager::loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx) { +bool GuiManager::loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx, bool forced) { // If we are asked to reload the currently active theme, just do nothing // FIXME: Actually, why? It might be desirable at times to force a theme reload... - if (_theme && id == _theme->getThemeId() && gfx == _theme->getGraphicsMode()) - return true; + if (!forced) + if (_theme && id == _theme->getThemeId() && gfx == _theme->getGraphicsMode()) + return true; ThemeEngine *newTheme = 0; @@ -218,6 +224,13 @@ Dialog *GuiManager::getTopDialog() const { return _dialogStack.top(); } +static void tooltipCallback(void *ref) { + GuiManager *guiManager = (GuiManager *)ref; + + guiManager->getTooltip()->setVisible(true); + g_system->getTimerManager()->removeTimerProc(&tooltipCallback); +} + void GuiManager::runLoop() { Dialog *activeDialog = getTopDialog(); bool didSaveState = false; @@ -276,6 +289,8 @@ void GuiManager::runLoop() { } Common::Event event; + + bool eventTookplace = false; while (eventMan->pollEvent(event)) { // The top dialog can change during the event loop. In that case, flush all the @@ -298,16 +313,21 @@ void GuiManager::runLoop() { switch (event.type) { case Common::EVENT_KEYDOWN: activeDialog->handleKeyDown(event.kbd); + eventTookplace = true; break; case Common::EVENT_KEYUP: activeDialog->handleKeyUp(event.kbd); + eventTookplace = true; break; case Common::EVENT_MOUSEMOVE: activeDialog->handleMouseMoved(mouse.x, mouse.y, 0); + _tooltip->setMouseXY(mouse.x, mouse.y); + eventTookplace = true; break; // We don't distinguish between mousebuttons (for now at least) case Common::EVENT_LBUTTONDOWN: case Common::EVENT_RBUTTONDOWN: + eventTookplace = true; button = (event.type == Common::EVENT_LBUTTONDOWN ? 1 : 2); time = _system->getMillis(); if (_lastClick.count && (time < _lastClick.time + kDoubleClickDelay) @@ -324,18 +344,22 @@ void GuiManager::runLoop() { break; case Common::EVENT_LBUTTONUP: case Common::EVENT_RBUTTONUP: + eventTookplace = true; button = (event.type == Common::EVENT_LBUTTONUP ? 1 : 2); activeDialog->handleMouseUp(mouse.x, mouse.y, button, _lastClick.count); break; case Common::EVENT_WHEELUP: + eventTookplace = true; activeDialog->handleMouseWheel(mouse.x, mouse.y, -1); break; case Common::EVENT_WHEELDOWN: + eventTookplace = true; activeDialog->handleMouseWheel(mouse.x, mouse.y, 1); break; case Common::EVENT_QUIT: return; case Common::EVENT_SCREEN_CHANGED: + eventTookplace = true; screenChange(); break; default: @@ -343,6 +367,13 @@ void GuiManager::runLoop() { } } + if (eventTookplace) { + _tooltip->setVisible(false); + + _system->getTimerManager()->removeTimerProc(&tooltipCallback); + _system->getTimerManager()->installTimerProc(&tooltipCallback, 2*1000000, this); + } + // Delay for a moment _system->delayMillis(10); } diff --git a/gui/GuiManager.h b/gui/GuiManager.h index 892d1aa3ac..2a187a92f9 100644 --- a/gui/GuiManager.h +++ b/gui/GuiManager.h @@ -60,6 +60,7 @@ typedef Common::FixedStack<Dialog *> DialogStack; */ class GuiManager : public Common::Singleton<GuiManager> { friend class Dialog; + friend class Tooltip; friend class Common::Singleton<SingletonBaseType>; GuiManager(); ~GuiManager(); @@ -71,7 +72,7 @@ public: bool isActive() const { return ! _dialogStack.empty(); } - bool loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx = ThemeEngine::kGfxDisabled); + bool loadNewTheme(Common::String id, ThemeEngine::GraphicsMode gfx = ThemeEngine::kGfxDisabled, bool force = false); ThemeEngine *theme() { return _theme; } ThemeEval *xmlEval() { return _theme->getEvaluator(); } @@ -91,6 +92,9 @@ public: * @return true if the a screen change indeed occurred, false otherwise */ bool checkScreenChange(); + + Tooltip *getTooltip() { return _tooltip; } + protected: enum RedrawStatus { kRedrawDisabled = 0, @@ -114,9 +118,11 @@ protected: bool _useStdCursor; + Tooltip *_tooltip; + // position and time of last mouse click (used to detect double clicks) struct { - int16 x, y; // Position of mouse when the click occured + int16 x, y; // Position of mouse when the click occurred uint32 time; // Time int count; // How often was it already pressed? } _lastClick; diff --git a/gui/KeysDialog.cpp b/gui/KeysDialog.cpp index b80dd200bb..897dd8c741 100644 --- a/gui/KeysDialog.cpp +++ b/gui/KeysDialog.cpp @@ -25,6 +25,7 @@ #include "gui/KeysDialog.h" #include "gui/Actions.h" +#include "common/translation.h" #include <SDL_keyboard.h> #ifdef _WIN32_WCE @@ -40,15 +41,15 @@ enum { KeysDialog::KeysDialog(const Common::String &title) : GUI::Dialog("KeysDialog") { - new ButtonWidget(this, "KeysDialog.Map", "Map", kMapCmd, 0); - new ButtonWidget(this, "KeysDialog.Ok", "OK", kOKCmd, 0); - new ButtonWidget(this, "KeysDialog.Cancel", "Cancel", kCloseCmd, 0); + new ButtonWidget(this, "KeysDialog.Map", _("Map"), 0, kMapCmd); + new ButtonWidget(this, "KeysDialog.Ok", _("OK"), 0, kOKCmd); + new ButtonWidget(this, "KeysDialog.Cancel", _("Cancel"), 0, kCloseCmd); _actionsList = new ListWidget(this, "KeysDialog.List"); _actionsList->setNumberingMode(kListNumberingZero); _actionTitle = new StaticTextWidget(this, "KeysDialog.Action", title); - _keyMapping = new StaticTextWidget(this, "KeysDialog.Mapping", "Select an action and click 'Map'"); + _keyMapping = new StaticTextWidget(this, "KeysDialog.Mapping", _("Select an action and click 'Map'")); _actionTitle->setFlags(WIDGET_CLEARBG); _keyMapping->setFlags(WIDGET_CLEARBG); @@ -79,9 +80,9 @@ void KeysDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { key = key - Common::ASCII_F1 + SDLK_F1; #endif if (key != 0) - sprintf(selection, "Associated key : %s", SDL_GetKeyName((SDLKey)key)); + sprintf(selection, _("Associated key : %s"), SDL_GetKeyName((SDLKey)key)); else - sprintf(selection, "Associated key : none"); + sprintf(selection, _("Associated key : none")); _keyMapping->setLabel(selection); _keyMapping->draw(); @@ -89,7 +90,7 @@ void KeysDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { break; case kMapCmd: if (_actionsList->getSelected() < 0) { - _actionTitle->setLabel("Please select an action"); + _actionTitle->setLabel(_("Please select an action")); } else { char selection[100]; @@ -101,11 +102,11 @@ void KeysDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { key = key - Common::ASCII_F1 + SDLK_F1; #endif if (key != 0) - sprintf(selection, "Associated key : %s", SDL_GetKeyName((SDLKey)key)); + sprintf(selection, _("Associated key : %s"), SDL_GetKeyName((SDLKey)key)); else - sprintf(selection, "Associated key : none"); + sprintf(selection, _("Associated key : none")); - _actionTitle->setLabel("Press the key to associate"); + _actionTitle->setLabel(_("Press the key to associate")); _keyMapping->setLabel(selection); _keyMapping->draw(); Actions::Instance()->beginMapping(true); @@ -140,11 +141,11 @@ void KeysDialog::handleKeyUp(Common::KeyState state) { Actions::Instance()->setMapping((ActionType)_actionSelected, state.ascii); if (state.ascii != 0) - sprintf(selection, "Associated key : %s", SDL_GetKeyName((SDLKey) state.keycode)); + sprintf(selection, _("Associated key : %s"), SDL_GetKeyName((SDLKey) state.keycode)); else - sprintf(selection, "Associated key : none"); + sprintf(selection, _("Associated key : none")); - _actionTitle->setLabel("Choose an action to map"); + _actionTitle->setLabel(_("Choose an action to map")); _keyMapping->setLabel(selection); _keyMapping->draw(); _actionTitle->draw(); diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index 97dde29824..e08bc09b0b 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -36,8 +36,8 @@ namespace GUI { -ListWidget::ListWidget(Dialog *boss, const String &name, uint32 cmd) - : EditableWidget(boss, name), _cmd(cmd) { +ListWidget::ListWidget(Dialog *boss, const String &name, const char *tooltip, uint32 cmd) + : EditableWidget(boss, name, tooltip), _cmd(cmd) { _scrollBar = NULL; _textWidth = NULL; @@ -68,8 +68,8 @@ ListWidget::ListWidget(Dialog *boss, const String &name, uint32 cmd) _editColor = ThemeEngine::kFontColorNormal; } -ListWidget::ListWidget(Dialog *boss, int x, int y, int w, int h, uint32 cmd) - : EditableWidget(boss, x, y, w, h), _cmd(cmd) { +ListWidget::ListWidget(Dialog *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd) + : EditableWidget(boss, x, y, w, h, tooltip), _cmd(cmd) { _scrollBar = NULL; _textWidth = NULL; diff --git a/gui/ListWidget.h b/gui/ListWidget.h index a3fb825761..3858fa6de2 100644 --- a/gui/ListWidget.h +++ b/gui/ListWidget.h @@ -87,8 +87,8 @@ protected: ThemeEngine::FontColor _editColor; public: - ListWidget(Dialog *boss, const String &name, uint32 cmd = 0); - ListWidget(Dialog *boss, int x, int y, int w, int h, uint32 cmd = 0); + ListWidget(Dialog *boss, const String &name, const char *tooltip = 0, uint32 cmd = 0); + ListWidget(Dialog *boss, int x, int y, int w, int h, const char *tooltip = 0, uint32 cmd = 0); virtual ~ListWidget(); virtual Widget *findWidget(int x, int y); diff --git a/gui/PopUpWidget.cpp b/gui/PopUpWidget.cpp index 7463399e0b..1bd9cc5063 100644 --- a/gui/PopUpWidget.cpp +++ b/gui/PopUpWidget.cpp @@ -378,8 +378,8 @@ void PopUpDialog::drawMenuEntry(int entry, bool hilite) { // PopUpWidget // -PopUpWidget::PopUpWidget(GuiObject *boss, const String &name) - : Widget(boss, name), CommandSender(boss) { +PopUpWidget::PopUpWidget(GuiObject *boss, const String &name, const char *tooltip) + : Widget(boss, name, tooltip), CommandSender(boss) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG | WIDGET_RETAIN_FOCUS | WIDGET_IGNORE_DRAG); _type = kPopUpWidget; diff --git a/gui/PopUpWidget.h b/gui/PopUpWidget.h index bd1d3b3918..f2c1728b52 100644 --- a/gui/PopUpWidget.h +++ b/gui/PopUpWidget.h @@ -59,13 +59,14 @@ protected: int _rightPadding; public: - PopUpWidget(GuiObject *boss, const String &name); + PopUpWidget(GuiObject *boss, const String &name, const char *tooltip = 0); void handleMouseDown(int x, int y, int button, int clickCount); void handleMouseWheel(int x, int y, int direction); void appendEntry(const String &entry, uint32 tag = (uint32)-1); void clearEntries(); + int numEntries() { return _entries.size(); } /** Select the entry at the given index. */ void setSelected(int item); diff --git a/gui/ScrollBarWidget.cpp b/gui/ScrollBarWidget.cpp index f6b36b3aa0..f4aaa8ffc9 100644 --- a/gui/ScrollBarWidget.cpp +++ b/gui/ScrollBarWidget.cpp @@ -26,6 +26,8 @@ #include "gui/dialog.h" #include "gui/GuiManager.h" +#include "common/timer.h" + namespace GUI { #define UP_DOWN_BOX_HEIGHT (_w+1) @@ -47,6 +49,28 @@ ScrollBarWidget::ScrollBarWidget(GuiObject *boss, int x, int y, int w, int h) _currentPos = 0; } +static void upArrowRepeater(void *ref) { + ScrollBarWidget *sb = (ScrollBarWidget *)ref; + int old_pos = sb->_currentPos; + + sb->_currentPos -= 3; + sb->checkBounds(old_pos); + + g_system->getTimerManager()->removeTimerProc(&upArrowRepeater); + g_system->getTimerManager()->installTimerProc(&upArrowRepeater, 1000000/10, ref); +} + +static void downArrowRepeater(void *ref) { + ScrollBarWidget *sb = (ScrollBarWidget *)ref; + int old_pos = sb->_currentPos; + + sb->_currentPos += 3; + sb->checkBounds(old_pos); + + g_system->getTimerManager()->removeTimerProc(&downArrowRepeater); + g_system->getTimerManager()->installTimerProc(&downArrowRepeater, 1000000/10, ref); +} + void ScrollBarWidget::handleMouseDown(int x, int y, int button, int clickCount) { int old_pos = _currentPos; @@ -58,10 +82,12 @@ void ScrollBarWidget::handleMouseDown(int x, int y, int button, int clickCount) // Up arrow _currentPos--; _draggingPart = kUpArrowPart; + g_system->getTimerManager()->installTimerProc(&upArrowRepeater, 1000000/2, this); } else if (y >= _h - UP_DOWN_BOX_HEIGHT) { // Down arrow _currentPos++; _draggingPart = kDownArrowPart; + g_system->getTimerManager()->installTimerProc(&downArrowRepeater, 1000000/2, this); } else if (y < _sliderPos) { _currentPos -= _entriesPerPage - 1; } else if (y >= _sliderPos + _sliderHeight) { @@ -77,6 +103,9 @@ void ScrollBarWidget::handleMouseDown(int x, int y, int button, int clickCount) void ScrollBarWidget::handleMouseUp(int x, int y, int button, int clickCount) { _draggingPart = kNoPart; + + g_system->getTimerManager()->removeTimerProc(&upArrowRepeater); + g_system->getTimerManager()->removeTimerProc(&downArrowRepeater); } void ScrollBarWidget::handleMouseWheel(int x, int y, int direction) { diff --git a/gui/ScrollBarWidget.h b/gui/ScrollBarWidget.h index 9379736f05..dd2b702686 100644 --- a/gui/ScrollBarWidget.h +++ b/gui/ScrollBarWidget.h @@ -73,9 +73,10 @@ public: // should these accessors force a redraw? void recalc(); + void checkBounds(int old_pos); + protected: void drawWidget(); - void checkBounds(int old_pos); }; } // End of namespace GUI diff --git a/gui/TabWidget.cpp b/gui/TabWidget.cpp index 3eb45297f3..ca409e50ab 100644 --- a/gui/TabWidget.cpp +++ b/gui/TabWidget.cpp @@ -37,12 +37,12 @@ enum { }; TabWidget::TabWidget(GuiObject *boss, int x, int y, int w, int h) - : Widget(boss, x, y, w, h) { + : Widget(boss, x, y, w, h), _bodyBackgroundType(GUI::ThemeEngine::kDialogBackgroundDefault) { init(); } TabWidget::TabWidget(GuiObject *boss, const String &name) - : Widget(boss, name) { + : Widget(boss, name), _bodyBackgroundType(GUI::ThemeEngine::kDialogBackgroundDefault) { init(); } @@ -56,15 +56,20 @@ void TabWidget::init() { _tabHeight = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Height"); _titleVPad = g_gui.xmlEval()->getVar("Globals.TabWidget.Tab.Padding.Top"); - _butRP = g_gui.xmlEval()->getVar("Globals.TabWidget.navButtonPadding.Right", 0); + _bodyTP = g_gui.xmlEval()->getVar("Globals.TabWidget.Body.Padding.Top"); + _bodyBP = g_gui.xmlEval()->getVar("Globals.TabWidget.Body.Padding.Bottom"); + _bodyLP = g_gui.xmlEval()->getVar("Globals.TabWidget.Body.Padding.Left"); + _bodyRP = g_gui.xmlEval()->getVar("Globals.TabWidget.Body.Padding.Right"); + + _butRP = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButtonPadding.Right", 0); _butTP = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Padding.Top", 0); _butW = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Width", 10); _butH = g_gui.xmlEval()->getVar("Globals.TabWidget.NavButton.Height", 10); int x = _w - _butRP - _butW * 2 - 2; int y = _butTP - _tabHeight; - _navLeft = new ButtonWidget(this, x, y, _butW, _butH, "<", kCmdLeft, 0); - _navRight = new ButtonWidget(this, x + _butW + 2, y, _butW, _butH, ">", kCmdRight, 0); + _navLeft = new ButtonWidget(this, x, y, _butW, _butH, "<", 0, kCmdLeft); + _navRight = new ButtonWidget(this, x + _butW + 2, y, _butW, _butH, ">", 0, kCmdRight); } TabWidget::~TabWidget() { @@ -279,11 +284,14 @@ void TabWidget::drawWidget() { for (int i = _firstVisibleTab; i < (int)_tabs.size(); ++i) { tabs.push_back(_tabs[i].title); } + g_gui.theme()->drawDialogBackground(Common::Rect(_x + _bodyLP, _y + _bodyTP, _x+_w-_bodyRP, _y+_h-_bodyBP), _bodyBackgroundType); + g_gui.theme()->drawTab(Common::Rect(_x, _y, _x+_w, _y+_h), _tabHeight, _tabWidth, tabs, _activeTab - _firstVisibleTab, 0, _titleVPad); } void TabWidget::draw() { Widget::draw(); + if (_tabWidth * _tabs.size() > _w) { _navLeft->draw(); _navRight->draw(); diff --git a/gui/TabWidget.h b/gui/TabWidget.h index 81544c2de7..e7b8733d8f 100644 --- a/gui/TabWidget.h +++ b/gui/TabWidget.h @@ -46,6 +46,9 @@ protected: int _tabWidth; int _tabHeight; + int _bodyRP, _bodyTP, _bodyLP, _bodyBP; + ThemeEngine::DialogBackground _bodyBackgroundType; + int _titleVPad; int _butRP, _butTP, _butW, _butH; diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index b472ad0535..30bacbb617 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -30,6 +30,7 @@ #include "common/fs.h" #include "common/unzip.h" #include "common/tokenizer.h" +#include "common/translation.h" #include "graphics/colormasks.h" #include "graphics/cursorman.h" @@ -189,6 +190,10 @@ static const DrawDataInfo kDrawDataDefaults[] = { {kDDCheckboxDisabled, "checkbox_disabled", true, kDDNone}, {kDDCheckboxSelected, "checkbox_selected", false, kDDCheckboxDefault}, + {kDDRadiobuttonDefault, "radiobutton_default", true, kDDNone}, + {kDDRadiobuttonDisabled, "radiobutton_disabled", true, kDDNone}, + {kDDRadiobuttonSelected, "radiobutton_selected", false, kDDRadiobuttonDefault}, + {kDDTabActive, "tab_active", false, kDDTabInactive}, {kDDTabInactive, "tab_inactive", true, kDDNone}, {kDDTabBackground, "tab_background", true, kDDNone}, @@ -329,10 +334,10 @@ ThemeEngine::~ThemeEngine() { * Rendering mode management *********************************************************/ const ThemeEngine::Renderer ThemeEngine::_rendererModes[] = { - { "Disabled GFX", "none", kGfxDisabled }, - { "Standard Renderer (16bpp)", "normal_16bpp", kGfxStandard16bit }, + { _s("Disabled GFX"), "none", kGfxDisabled }, + { _s("Standard Renderer (16bpp)"), "normal_16bpp", kGfxStandard16bit }, #ifndef DISABLE_FANCY_THEMES - { "Antialiased Renderer (16bpp)", "aa_16bpp", kGfxAntialias16bit } + { _s("Antialiased Renderer (16bpp)"), "aa_16bpp", kGfxAntialias16bit } #endif }; @@ -392,17 +397,12 @@ bool ThemeEngine::init() { if (!_themeArchive && !_themeFile.empty()) { Common::FSNode node(_themeFile); if (node.getName().hasSuffix(".zip") && !node.isDirectory()) { -#ifdef USE_ZLIB Common::Archive *zipArchive = Common::makeZipArchive(node); if (!zipArchive) { warning("Failed to open Zip archive '%s'.", node.getPath().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); } @@ -563,10 +563,17 @@ bool ThemeEngine::addFont(TextData textId, const Common::String &file) { if (file == "default") { _texts[textId]->_fontPtr = _font; } else { - _texts[textId]->_fontPtr = FontMan.getFontByName(file); + Common::String localized = genLocalizedFontFilename(file.c_str()); + // Try built-in fonts + _texts[textId]->_fontPtr = FontMan.getFontByName(localized); if (!_texts[textId]->_fontPtr) { - _texts[textId]->_fontPtr = loadFont(file); + // First try to load localized font + _texts[textId]->_fontPtr = loadFont(localized); + + // Fallback to non-localized font + if (!_texts[textId]->_fontPtr) + _texts[textId]->_fontPtr = loadFont(file); if (!_texts[textId]->_fontPtr) error("Couldn't load font '%s'", file.c_str()); @@ -884,6 +891,32 @@ void ThemeEngine::drawCheckbox(const Common::Rect &r, const Common::String &str, queueDDText(getTextData(dd), getTextColor(dd), r2, str, false, false, _widgets[kDDCheckboxDefault]->_textAlignH, _widgets[dd]->_textAlignV); } +void ThemeEngine::drawRadiobutton(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state) { + if (!ready()) + return; + + Common::Rect r2 = r; + DrawData dd = kDDRadiobuttonDefault; + + if (checked) + dd = kDDRadiobuttonSelected; + + if (state == kStateDisabled) + dd = kDDRadiobuttonDisabled; + + const int checkBoxSize = MIN((int)r.height(), getFontHeight()); + + r2.bottom = r2.top + checkBoxSize; + r2.right = r2.left + checkBoxSize; + + queueDD(dd, r2); + + r2.left = r2.right + checkBoxSize; + r2.right = r.right; + + queueDDText(getTextData(dd), getTextColor(dd), r2, str, false, false, _widgets[kDDRadiobuttonDefault]->_textAlignH, _widgets[dd]->_textAlignV); +} + void ThemeEngine::drawSlider(const Common::Rect &r, int width, WidgetStateInfo state) { if (!ready()) return; @@ -1039,7 +1072,7 @@ void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, co } } -void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color) { +void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color, bool restore) { if (!ready()) return; @@ -1090,13 +1123,7 @@ void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, Wid return; } - TextData textId = kTextDataNone; - if (font == kFontStyleNormal) - textId = kTextDataNormalFont; - else - textId = kTextDataDefault; - - bool restore = true; + TextData textId = fontStyleToData(font); switch (inverted) { case kTextInversion: @@ -1138,7 +1165,69 @@ void ThemeEngine::debugWidgetPosition(const char *name, const Common::Rect &r) { _screen.vLine(r.right, r.top, r.bottom, 0xFFFF); } +ThemeEngine::StoredState *ThemeEngine::storeState(const Common::Rect &r) { + StoredState *state = new StoredState; + byte *dst; + byte *src; + state->r.top = r.top; + state->r.bottom = r.bottom; + state->r.left = r.left; + state->r.right = r.right; + + state->r.clip(_screen.w, _screen.h); + + state->screen.create(state->r.width(), state->r.height(), _screen.bytesPerPixel); + state->backBuffer.create(state->r.width(), state->r.height(), _backBuffer.bytesPerPixel); + + src = (byte *)_screen.getBasePtr(state->r.left, state->r.top); + dst = (byte *)state->screen.getBasePtr(0, 0); + + for (int i = state->r.height(); i > 0; i--) { + memcpy(dst, src, state->r.width() * _screen.bytesPerPixel); + src += _screen.pitch; + dst += state->screen.pitch; + } + + src = (byte *)_backBuffer.getBasePtr(state->r.left, state->r.top); + dst = (byte *)state->backBuffer.getBasePtr(0, 0); + + for (int i = state->r.height(); i > 0; i--) { + memcpy(dst, src, state->r.width() * _backBuffer.bytesPerPixel); + src += _backBuffer.pitch; + dst += state->backBuffer.pitch; + } + + return state; +} + +void ThemeEngine::restoreState(StoredState *state) { + byte *dst; + byte *src; + + if (!state) + return; + + src = (byte *)state->screen.getBasePtr(0, 0); + dst = (byte *)_screen.getBasePtr(state->r.left, state->r.top); + + for (int i = state->r.height(); i > 0; i--) { + memcpy(dst, src, state->r.width() * _screen.bytesPerPixel); + src += state->screen.pitch; + dst += _screen.pitch; + } + + src = (byte *)state->backBuffer.getBasePtr(0, 0); + dst = (byte *)_backBuffer.getBasePtr(state->r.left, state->r.top); + + for (int i = state->r.height(); i > 0; i--) { + memcpy(dst, src, state->r.width() * _backBuffer.bytesPerPixel); + src += state->backBuffer.pitch; + dst += _backBuffer.pitch; + } + + addDirtyRect(state->r); +} /********************************************************** * Screen/overlay management @@ -1408,6 +1497,34 @@ Common::String ThemeEngine::genCacheFilename(const char *filename) { return Common::String(); } +Common::String ThemeEngine::genLocalizedFontFilename(const char *filename) { +#ifndef USE_TRANSLATION + return Common::String(filename); +#else + + Common::String result; + bool pointPassed = false; + + for (const char *p = filename; *p != 0; p++) { + if (!pointPassed) { + if (*p != '.') { + result += *p; + } else { + result += "-"; + result += TransMan.getCurrentCharset(); + result += *p; + + pointPassed = true; + } + } else { + result += *p; + } + } + + return result; +#endif +} + /********************************************************** * Static Theme XML functions @@ -1441,7 +1558,6 @@ bool ThemeEngine::themeConfigUsable(const Common::FSNode &node, Common::String & bool foundHeader = false; if (node.getName().hasSuffix(".zip") && !node.isDirectory()) { -#ifdef USE_ZLIB Common::Archive *zipArchive = Common::makeZipArchive(node); if (zipArchive && zipArchive->hasFile("THEMERC")) { // Open THEMERC from the ZIP file. @@ -1454,7 +1570,6 @@ bool ThemeEngine::themeConfigUsable(const Common::FSNode &node, Common::String & // reference to zipArchive anywhere. This could change if we // ever modify ZipArchive::createReadStreamForMember. delete zipArchive; -#endif } else if (node.isDirectory()) { Common::FSNode headerfile = node.getChild("THEMERC"); if (!headerfile.exists() || !headerfile.isReadable() || headerfile.isDirectory()) @@ -1550,7 +1665,6 @@ void ThemeEngine::listUsableThemes(const Common::FSNode &node, Common::List<Them } Common::FSList fileList; -#ifdef USE_ZLIB // Check all files. We need this to find all themes inside ZIP archives. if (!node.getChildren(fileList, Common::FSNode::kListFilesOnly)) return; @@ -1577,7 +1691,6 @@ void ThemeEngine::listUsableThemes(const Common::FSNode &node, Common::List<Them } fileList.clear(); -#endif // Check if we exceeded the given recursion depth if (depth - 1 == -1) diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h index 2da1c3a014..f0d4e2585d 100644 --- a/gui/ThemeEngine.h +++ b/gui/ThemeEngine.h @@ -82,6 +82,10 @@ enum DrawData { kDDCheckboxDisabled, kDDCheckboxSelected, + kDDRadiobuttonDefault, + kDDRadiobuttonDisabled, + kDDRadiobuttonSelected, + kDDTabActive, kDDTabInactive, kDDTabBackground, @@ -108,6 +112,7 @@ enum TextData { kTextDataDefault = 0, kTextDataButton, kTextDataNormalFont, + kTextDataTooltip, kTextDataMAX }; @@ -173,7 +178,7 @@ public: enum TextInversionState { kTextInversionNone, ///< Indicates that the text should not be drawn inverted kTextInversion, ///< Indicates that the text should be drawn inverted, but not focused - kTextInversionFocus ///< Indicates thte the test should be drawn inverted, and focused + kTextInversionFocus ///< Indicates that the text should be drawn inverted, and focused }; enum ScrollbarState { @@ -192,6 +197,7 @@ public: kFontStyleFixedNormal = 3, ///< Fixed size font. kFontStyleFixedBold = 4, ///< Fixed size bold font. kFontStyleFixedItalic = 5, ///< Fixed size italic font. + kFontStyleTooltip = 6, ///< Tiny console font kFontStyleMax }; @@ -255,6 +261,17 @@ public: void enable(); void disable(); + struct StoredState { + Common::Rect r; + Graphics::Surface screen; + Graphics::Surface backBuffer; + + StoredState() {} + }; + + StoredState *storeState(const Common::Rect &r); + void restoreState(StoredState *state); + /** * Implementation of the GUI::Theme API. Called when a * new dialog is opened. Note that the boolean parameter @@ -280,6 +297,8 @@ public: TextData fontStyleToData(FontStyle font) const { if (font == kFontStyleNormal) return kTextDataNormalFont; + if (font == kFontStyleTooltip) + return kTextDataTooltip; return kTextDataDefault; } @@ -312,6 +331,9 @@ public: void drawCheckbox(const Common::Rect &r, const Common::String &str, bool checked, WidgetStateInfo state = kStateEnabled); + void drawRadiobutton(const Common::Rect &r, const Common::String &str, + bool checked, WidgetStateInfo state = kStateEnabled); + void drawTab(const Common::Rect &r, int tabHeight, int tabWidth, const Common::Array<Common::String> &tabs, int active, uint16 hints, int titleVPad, WidgetStateInfo state = kStateEnabled); @@ -329,7 +351,7 @@ public: void drawDialogBackground(const Common::Rect &r, DialogBackground type, WidgetStateInfo state = kStateEnabled); - void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal); + void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal, bool restore = true); void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state = kStateEnabled, FontColor color = kFontColorNormal); @@ -517,6 +539,7 @@ protected: const Graphics::Font *loadFont(const Common::String &filename); const Graphics::Font *loadFontFromArchive(const Common::String &filename); Common::String genCacheFilename(const char *filename); + Common::String genLocalizedFontFilename(const char *filename); /** * Actual Dirty Screen handling function. diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp index e22d440bd9..4cabf6ad2e 100644 --- a/gui/ThemeParser.cpp +++ b/gui/ThemeParser.cpp @@ -42,7 +42,8 @@ struct TextDataInfo { static const TextDataInfo kTextDataDefaults[] = { { kTextDataDefault, "text_default" }, { kTextDataButton, "text_button" }, - { kTextDataNormalFont, "text_normal" } + { kTextDataNormalFont, "text_normal" }, + { kTextDataTooltip, "tooltip_normal" } }; diff --git a/gui/about.cpp b/gui/about.cpp index 8b2f470bf6..3caab084ca 100644 --- a/gui/about.cpp +++ b/gui/about.cpp @@ -27,6 +27,7 @@ #include "base/version.h" #include "common/events.h" #include "common/system.h" +#include "common/translation.h" #include "common/util.h" #include "gui/about.h" #include "gui/GuiManager.h" @@ -92,22 +93,25 @@ AboutDialog::AboutDialog() version += gScummVMVersion; _lines.push_back(version); - Common::String date("C2""(built on "); - date += gScummVMBuildDate; - date += ')'; - _lines.push_back(date); + Common::String date = Common::String::printf(_("(built on %s)"), gScummVMBuildDate); + _lines.push_back("C2" + date); for (i = 0; i < ARRAYSIZE(copyright_text); i++) addLine(copyright_text[i]); - addLine("C1""Features compiled in:"); - Common::String features("C0"); - features += gScummVMFeatures; + Common::String features("C1"); + features += _("Features compiled in:"); addLine(features.c_str()); + Common::String featureList("C0"); + featureList += gScummVMFeatures; + addLine(featureList.c_str()); _lines.push_back(""); - addLine("C1""Available engines:"); + Common::String engines("C1"); + engines += _("Available engines:"); + addLine(engines.c_str()); + const EnginePlugin::List &plugins = EngineMan.getPlugins(); EnginePlugin::List::const_iterator iter = plugins.begin(); for (; iter != plugins.end(); ++iter) { diff --git a/gui/browser.cpp b/gui/browser.cpp index c090742988..0d95e5397b 100644 --- a/gui/browser.cpp +++ b/gui/browser.cpp @@ -30,6 +30,8 @@ #include "common/system.h" #include "common/algorithm.h" +#include "common/translation.h" + namespace GUI { enum { @@ -64,9 +66,9 @@ BrowserDialog::BrowserDialog(const char *title, bool dirBrowser) _backgroundType = GUI::ThemeEngine::kDialogBackgroundPlain; // Buttons - new ButtonWidget(this, "Browser.Up", "Go up", kGoUpCmd, 0); - new ButtonWidget(this, "Browser.Cancel", "Cancel", kCloseCmd, 0); - new ButtonWidget(this, "Browser.Choose", "Choose", kChooseCmd, 0); + new ButtonWidget(this, "Browser.Up", _("Go up"), _("Go to previous directory level"), kGoUpCmd); + new ButtonWidget(this, "Browser.Cancel", _("Cancel"), 0, kCloseCmd); + new ButtonWidget(this, "Browser.Choose", _("Choose"), 0, kChooseCmd); } void BrowserDialog::open() { diff --git a/gui/chooser.cpp b/gui/chooser.cpp index 0155bb2afb..a7b453c957 100644 --- a/gui/chooser.cpp +++ b/gui/chooser.cpp @@ -23,6 +23,7 @@ */ #include "common/system.h" +#include "common/translation.h" #include "gui/chooser.h" #include "gui/GuiManager.h" #include "gui/ListWidget.h" @@ -45,8 +46,8 @@ ChooserDialog::ChooserDialog(const String &title, String dialogId) _list->setEditable(false); // Buttons - new ButtonWidget(this, dialogId + ".Cancel", "Cancel", kCloseCmd, 0); - _chooseButton = new ButtonWidget(this, dialogId + ".Choose", "Choose", kChooseCmd, 0); + new ButtonWidget(this, dialogId + ".Cancel", _("Cancel"), 0, kCloseCmd); + _chooseButton = new ButtonWidget(this, dialogId + ".Choose", _("Choose"), 0, kChooseCmd); _chooseButton->setEnabled(false); } diff --git a/gui/console.cpp b/gui/console.cpp index 37d3bd6aa5..a2aa56f5b3 100644 --- a/gui/console.cpp +++ b/gui/console.cpp @@ -156,7 +156,9 @@ void ConsoleDialog::open() { _slideMode = kDownSlideMode; Dialog::open(); - if (_promptStartPos == -1) { + if ((_promptStartPos == -1) || (_currentPos > _promptEndPos)) { + // we print a prompt, if this is the first time we are called or if the + // engine wrote onto us since the last call print(PROMPT); _promptStartPos = _promptEndPos = _currentPos; } diff --git a/gui/credits.h b/gui/credits.h index 0df894a642..ae658e1196 100644 --- a/gui/credits.h +++ b/gui/credits.h @@ -363,6 +363,29 @@ static const char *credits[] = { "C0""Johannes Schickel", "", "", +"C1""Translations", +"C0""Thierry Crozat", +"C2""Translation Lead", +"C1""Catalan", +"C0""Jordi Vilalta Prat", +"", +"C1""French", +"C0""Thierry Crozat", +"", +"C1""German", +"C0""Simon Sawatzki", +"C0""Lothar Serra Mari", +"", +"C1""Hungarian", +"C0""Alex Bevilacqua", +"", +"C1""Italian", +"C0""Matteo Angelino", +"", +"C1""Russian", +"C0""Eugene Sandulenko", +"", +"", "C1""Websites (design)", "C0""Dob\363 Bal\341zs", "C2""Website design", @@ -479,7 +502,7 @@ static const char *credits[] = { "C0""Rune Orsval", "C2""Configuration file editor", "C0""Rickard Lind", -"C2""MT32->GM MIDI mapping magic, sound research", +"C2""MT-32->GM MIDI mapping magic, sound research", "C0""Rink Springer", "C2""Port to the DOS platform, several bug fixes", "C0""Robey Pointer", diff --git a/gui/dialog.cpp b/gui/dialog.cpp index 5e3a9a1927..e20b181c83 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -171,7 +171,7 @@ void Dialog::handleMouseDown(int x, int y, int button, int clickCount) { if (w && !(w->getFlags() & WIDGET_IGNORE_DRAG)) _dragWidget = w; - // If the click occured inside a widget which is not the currently + // If the click occurred inside a widget which is not the currently // focused one, change the focus to that widget. if (w && w != _focusedWidget && w->wantsFocus()) { setFocusWidget(w); diff --git a/gui/dialog.h b/gui/dialog.h index 5008f272ba..1845786044 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -44,6 +44,7 @@ enum { class Dialog : public GuiObject { friend class GuiManager; + friend class Tooltip; protected: Widget *_mouseWidget; Widget *_focusedWidget; diff --git a/gui/editable.cpp b/gui/editable.cpp index 058f08e233..755e34e380 100644 --- a/gui/editable.cpp +++ b/gui/editable.cpp @@ -28,13 +28,13 @@ namespace GUI { -EditableWidget::EditableWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd) - : Widget(boss, x, y, w, h), CommandSender(boss), _cmd(cmd) { +EditableWidget::EditableWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd) + : Widget(boss, x, y, w, h, tooltip), CommandSender(boss), _cmd(cmd) { init(); } -EditableWidget::EditableWidget(GuiObject *boss, const String &name, uint32 cmd) - : Widget(boss, name), CommandSender(boss), _cmd(cmd) { +EditableWidget::EditableWidget(GuiObject *boss, const String &name, const char *tooltip, uint32 cmd) + : Widget(boss, name, tooltip), CommandSender(boss), _cmd(cmd) { init(); } diff --git a/gui/editable.h b/gui/editable.h index 00cb3431a5..8ff5298511 100644 --- a/gui/editable.h +++ b/gui/editable.h @@ -55,8 +55,8 @@ protected: ThemeEngine::FontStyle _font; public: - EditableWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd = 0); - EditableWidget(GuiObject *boss, const String &name, uint32 cmd = 0); + EditableWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip = 0, uint32 cmd = 0); + EditableWidget(GuiObject *boss, const String &name, const char *tooltip = 0, uint32 cmd = 0); virtual ~EditableWidget(); void init(); diff --git a/gui/error.cpp b/gui/error.cpp index fbe09c5a02..3332eb533a 100644 --- a/gui/error.cpp +++ b/gui/error.cpp @@ -27,6 +27,8 @@ #include "gui/message.h" #include "gui/error.h" +#include "common/translation.h" + namespace GUI { void displayErrorDialog(const char *text) { @@ -37,7 +39,7 @@ void displayErrorDialog(const char *text) { void displayErrorDialog(Common::Error error, const char *extraText) { Common::String errorText(extraText); errorText += " "; - errorText += Common::errorToString(error); + errorText += _(Common::errorToString(error)); GUI::MessageDialog alert(errorText); alert.runModal(); } diff --git a/gui/launcher.cpp b/gui/launcher.cpp index 0f484c5233..1daf9ffd50 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -30,6 +30,7 @@ #include "common/util.h" #include "common/savefile.h" #include "common/system.h" +#include "common/translation.h" #include "gui/about.h" #include "gui/browser.h" @@ -87,8 +88,8 @@ enum { */ class DomainEditTextWidget : public EditTextWidget { public: - DomainEditTextWidget(GuiObject *boss, const String &name, const String &text) - : EditTextWidget(boss, name, text) { + DomainEditTextWidget(GuiObject *boss, const String &name, const String &text, const char *tooltip = 0) + : EditTextWidget(boss, name, text, tooltip) { } protected: @@ -166,30 +167,31 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) // // 1) The game tab // - tab->addTab("Game"); + tab->addTab(_("Game")); // GUI: Label & edit widget for the game ID - new StaticTextWidget(tab, "GameOptions_Game.Id", "ID:"); - _domainWidget = new DomainEditTextWidget(tab, "GameOptions_Game.Domain", _domain); + new StaticTextWidget(tab, "GameOptions_Game.Id", _("ID:"), _("Short game identifier used for referring to savegames and running the game from the command line")); + _domainWidget = new DomainEditTextWidget(tab, "GameOptions_Game.Domain", _domain, _("Short game identifier used for referring to savegames and running the game from the command line")); // GUI: Label & edit widget for the description - new StaticTextWidget(tab, "GameOptions_Game.Name", "Name:"); - _descriptionWidget = new EditTextWidget(tab, "GameOptions_Game.Desc", description); + new StaticTextWidget(tab, "GameOptions_Game.Name", _("Name:"), _("Full title of the game")); + _descriptionWidget = new EditTextWidget(tab, "GameOptions_Game.Desc", description, _("Full title of the game")); // Language popup - _langPopUpDesc = new StaticTextWidget(tab, "GameOptions_Game.LangPopupDesc", "Language:"); - _langPopUp = new PopUpWidget(tab, "GameOptions_Game.LangPopup"); - _langPopUp->appendEntry("<default>"); - _langPopUp->appendEntry(""); + _langPopUpDesc = new StaticTextWidget(tab, "GameOptions_Game.LangPopupDesc", _("Language:"), _("Language of the game. This will not turn your Spanish game version into English")); + _langPopUp = new PopUpWidget(tab, "GameOptions_Game.LangPopup", _("Language of the game. This will not turn your Spanish game version into English")); + _langPopUp->appendEntry(_("<default>"), 0); + _langPopUp->appendEntry("", 0); const Common::LanguageDescription *l = Common::g_languages; for (; l->code; ++l) { - _langPopUp->appendEntry(l->description, l->id); + if (checkGameGUIOptionLanguage(l->id, _guioptionsString)) + _langPopUp->appendEntry(l->description, l->id); } // Platform popup - _platformPopUpDesc = new StaticTextWidget(tab, "GameOptions_Game.PlatformPopupDesc", "Platform:"); - _platformPopUp = new PopUpWidget(tab, "GameOptions_Game.PlatformPopup"); - _platformPopUp->appendEntry("<default>"); + _platformPopUpDesc = new StaticTextWidget(tab, "GameOptions_Game.PlatformPopupDesc", _("Platform:"), _("Platform the game was originally designed for")); + _platformPopUp = new PopUpWidget(tab, "GameOptions_Game.PlatformPopup", _("Platform the game was originally designed for")); + _platformPopUp->appendEntry(_("<default>")); _platformPopUp->appendEntry(""); const Common::PlatformDescription *p = Common::g_platforms; for (; p->code; ++p) { @@ -199,18 +201,18 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) // // 3) The graphics tab // - _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? "Graphics" : "GFX"); + _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? _("Graphics") : _("GFX")); - _globalGraphicsOverride = new CheckboxWidget(tab, "GameOptions_Graphics.EnableTabCheckbox", "Override global graphic settings", kCmdGlobalGraphicsOverride, 0); + _globalGraphicsOverride = new CheckboxWidget(tab, "GameOptions_Graphics.EnableTabCheckbox", _("Override global graphic settings"), 0, kCmdGlobalGraphicsOverride); addGraphicControls(tab, "GameOptions_Graphics."); // // 4) The audio tab // - tab->addTab("Audio"); + tab->addTab(_("Audio")); - _globalAudioOverride = new CheckboxWidget(tab, "GameOptions_Audio.EnableTabCheckbox", "Override global audio settings", kCmdGlobalAudioOverride, 0); + _globalAudioOverride = new CheckboxWidget(tab, "GameOptions_Audio.EnableTabCheckbox", _("Override global audio settings"), 0, kCmdGlobalAudioOverride); addAudioControls(tab, "GameOptions_Audio."); addSubtitleControls(tab, "GameOptions_Audio."); @@ -218,18 +220,18 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) // // 5) The volume tab // - tab->addTab("Volume"); + tab->addTab(_("Volume")); - _globalVolumeOverride = new CheckboxWidget(tab, "GameOptions_Volume.EnableTabCheckbox", "Override global volume settings", kCmdGlobalVolumeOverride, 0); + _globalVolumeOverride = new CheckboxWidget(tab, "GameOptions_Volume.EnableTabCheckbox", _("Override global volume settings"), 0, kCmdGlobalVolumeOverride); addVolumeControls(tab, "GameOptions_Volume."); // // 6) The MIDI tab // - tab->addTab("MIDI"); + tab->addTab(_("MIDI")); - _globalMIDIOverride = new CheckboxWidget(tab, "GameOptions_MIDI.EnableTabCheckbox", "Override global MIDI settings", kCmdGlobalMIDIOverride, 0); + _globalMIDIOverride = new CheckboxWidget(tab, "GameOptions_MIDI.EnableTabCheckbox", _("Override global MIDI settings"), 0, kCmdGlobalMIDIOverride); if (_guioptions & Common::GUIO_NOMIDI) _globalMIDIOverride->setEnabled(false); @@ -239,30 +241,30 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) // // 2) The 'Path' tab // - tab->addTab("Paths"); + tab->addTab(_("Paths")); // These buttons have to be extra wide, or the text will be truncated // in the small version of the GUI. // GUI: Button + Label for the game path - new ButtonWidget(tab, "GameOptions_Paths.Gamepath", "Game Path:", kCmdGameBrowser, 0); + new ButtonWidget(tab, "GameOptions_Paths.Gamepath", _("Game Path:"), 0, kCmdGameBrowser); _gamePathWidget = new StaticTextWidget(tab, "GameOptions_Paths.GamepathText", gamePath); // GUI: Button + Label for the additional path - new ButtonWidget(tab, "GameOptions_Paths.Extrapath", "Extra Path:", kCmdExtraBrowser, 0); - _extraPathWidget = new StaticTextWidget(tab, "GameOptions_Paths.ExtrapathText", extraPath); + new ButtonWidget(tab, "GameOptions_Paths.Extrapath", _("Extra Path:"), _("Specifies path to additional data used the game"), kCmdExtraBrowser); + _extraPathWidget = new StaticTextWidget(tab, "GameOptions_Paths.ExtrapathText", extraPath, _("Specifies path to additional data used the game")); // GUI: Button + Label for the save path - new ButtonWidget(tab, "GameOptions_Paths.Savepath", "Save Path:", kCmdSaveBrowser, 0); - _savePathWidget = new StaticTextWidget(tab, "GameOptions_Paths.SavepathText", savePath); + new ButtonWidget(tab, "GameOptions_Paths.Savepath", _("Save Path:"), _("Specifies where your savegames are put"), kCmdSaveBrowser); + _savePathWidget = new StaticTextWidget(tab, "GameOptions_Paths.SavepathText", savePath, _("Specifies where your savegames are put")); // Activate the first tab tab->setActiveTab(0); _tabWidget = tab; // Add OK & Cancel buttons - new ButtonWidget(this, "GameOptions.Cancel", "Cancel", kCloseCmd, 0); - new ButtonWidget(this, "GameOptions.Ok", "OK", kOKCmd, 0); + new ButtonWidget(this, "GameOptions.Cancel", _("Cancel"), 0, kCloseCmd); + new ButtonWidget(this, "GameOptions.Ok", _("OK"), 0, kOKCmd); } void EditGameDialog::open() { @@ -270,12 +272,12 @@ void EditGameDialog::open() { String extraPath(ConfMan.get("extrapath", _domain)); if (extraPath.empty() || !ConfMan.hasKey("extrapath", _domain)) { - _extraPathWidget->setLabel("None"); + _extraPathWidget->setLabel(_("None")); } String savePath(ConfMan.get("savepath", _domain)); if (savePath.empty() || !ConfMan.hasKey("savepath", _domain)) { - _savePathWidget->setLabel("Default"); + _savePathWidget->setLabel(_("Default")); } int sel, i; @@ -310,17 +312,16 @@ void EditGameDialog::open() { // TODO: game path - const Common::LanguageDescription *l = Common::g_languages; const Common::Language lang = Common::parseLanguage(ConfMan.get("language", _domain)); - sel = 0; if (ConfMan.hasKey("language", _domain)) { - for (i = 0; l->code; ++l, ++i) { - if (lang == l->id) - sel = i + 2; - } + _langPopUp->setSelectedTag(lang); + } + + if (_langPopUp->numEntries() <= 3) { // If only one language is avaliable + _langPopUpDesc->setEnabled(false); + _langPopUp->setEnabled(false); } - _langPopUp->setSelected(sel); const Common::PlatformDescription *p = Common::g_platforms; @@ -349,11 +350,11 @@ void EditGameDialog::close() { ConfMan.set("path", gamePath, _domain); String extraPath(_extraPathWidget->getLabel()); - if (!extraPath.empty() && (extraPath != "None")) + if (!extraPath.empty() && (extraPath != _("None"))) ConfMan.set("extrapath", extraPath, _domain); String savePath(_savePathWidget->getLabel()); - if (!savePath.empty() && (savePath != "Default")) + if (!savePath.empty() && (savePath != _("Default"))) ConfMan.set("savepath", savePath, _domain); Common::Platform platform = (Common::Platform)_platformPopUp->getSelectedTag(); @@ -387,14 +388,14 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat draw(); break; case kCmdChooseSoundFontCmd: { - BrowserDialog browser("Select SoundFont", false); + BrowserDialog browser(_("Select SoundFont"), false); if (browser.runModal() > 0) { // User made this choice... Common::FSNode file(browser.getResult()); _soundFont->setLabel(file.getPath()); - if (!file.getPath().empty() && (file.getPath() != "None")) + if (!file.getPath().empty() && (file.getPath() != _("None"))) _soundFontClearButton->setEnabled(true); else _soundFontClearButton->setEnabled(false); @@ -406,7 +407,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat // Change path for the game case kCmdGameBrowser: { - BrowserDialog browser("Select directory with game data", true); + BrowserDialog browser(_("Select directory with game data"), true); if (browser.runModal() > 0) { // User made his choice... Common::FSNode dir(browser.getResult()); @@ -424,7 +425,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat // Change path for extra game data (eg, using sword cutscenes when playing via CD) case kCmdExtraBrowser: { - BrowserDialog browser("Select additional game directory", true); + BrowserDialog browser(_("Select additional game directory"), true); if (browser.runModal() > 0) { // User made his choice... Common::FSNode dir(browser.getResult()); @@ -436,7 +437,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat } // Change path for stored save game (perm and temp) data case kCmdSaveBrowser: { - BrowserDialog browser("Select directory for saved games", true); + BrowserDialog browser(_("Select directory for saved games"), true); if (browser.runModal() > 0) { // User made his choice... Common::FSNode dir(browser.getResult()); @@ -455,7 +456,7 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat || newDomain.hasPrefix("_") || newDomain == ConfigManager::kApplicationDomain || ConfMan.hasGameDomain(newDomain)) { - MessageDialog alert("This game ID is already taken. Please choose another one."); + MessageDialog alert(_("This game ID is already taken. Please choose another one.")); alert.runModal(); return; } @@ -496,39 +497,39 @@ LauncherDialog::LauncherDialog() new StaticTextWidget(this, "Launcher.Version", gScummVMFullVersion); #endif - new ButtonWidget(this, "Launcher.QuitButton", "Quit", kQuitCmd, 'Q'); - new ButtonWidget(this, "Launcher.AboutButton", "About...", kAboutCmd, 'B'); - new ButtonWidget(this, "Launcher.OptionsButton", "Options...", kOptionsCmd, 'O'); + new ButtonWidget(this, "Launcher.QuitButton", _("~Q~uit"), _("Quit ScummVM"), kQuitCmd); + new ButtonWidget(this, "Launcher.AboutButton", _("A~b~out..."), _("About ScummVM"), kAboutCmd); + new ButtonWidget(this, "Launcher.OptionsButton", _("~O~ptions..."), _("Change global ScummVM options"), kOptionsCmd); _startButton = - new ButtonWidget(this, "Launcher.StartButton", "Start", kStartCmd, 'S'); + new ButtonWidget(this, "Launcher.StartButton", _("~S~tart"), _("Start selected game"), kStartCmd); _loadButton = - new ButtonWidget(this, "Launcher.LoadGameButton", "Load...", kLoadGameCmd, 'L'); + new ButtonWidget(this, "Launcher.LoadGameButton", _("~L~oad..."), _("Load savegame for selected game"), kLoadGameCmd); // Above the lowest button rows: two more buttons (directly below the list box) _addButton = - new ButtonWidget(this, "Launcher.AddGameButton", "Add Game...", kAddGameCmd, 'A'); + new ButtonWidget(this, "Launcher.AddGameButton", _("~A~dd Game..."), _("Hold Shift for Mass Add"), kAddGameCmd); _editButton = - new ButtonWidget(this, "Launcher.EditGameButton", "Edit Game...", kEditGameCmd, 'E'); + new ButtonWidget(this, "Launcher.EditGameButton", _("~E~dit Game..."), _("Change game options"), kEditGameCmd); _removeButton = - new ButtonWidget(this, "Launcher.RemoveGameButton", "Remove Game", kRemoveGameCmd, 'R'); + new ButtonWidget(this, "Launcher.RemoveGameButton", _("~R~emove Game"), _("Remove game from the list. The game data files stay intact"), kRemoveGameCmd); // Search box _searchDesc = 0; #ifndef DISABLE_FANCY_THEMES _searchPic = 0; if (g_gui.xmlEval()->getVar("Globals.ShowSearchPic") == 1 && g_gui.theme()->supportsImages()) { - _searchPic = new GraphicsWidget(this, "Launcher.SearchPic"); + _searchPic = new GraphicsWidget(this, "Launcher.SearchPic", _("Search in game list")); _searchPic->setGfx(g_gui.theme()->getImageSurface(ThemeEngine::kImageSearch)); } else #endif - _searchDesc = new StaticTextWidget(this, "Launcher.SearchDesc", "Search:"); + _searchDesc = new StaticTextWidget(this, "Launcher.SearchDesc", _("Search:")); - _searchWidget = new EditTextWidget(this, "Launcher.Search", _search, kSearchCmd); - _searchClearButton = new ButtonWidget(this, "Launcher.SearchClearButton", "C", kSearchClearCmd, 0); + _searchWidget = new EditTextWidget(this, "Launcher.Search", _search, 0, kSearchCmd); + _searchClearButton = new ButtonWidget(this, "Launcher.SearchClearButton", "C", _("Clear value"), kSearchClearCmd); // Add list with game titles - _list = new ListWidget(this, "Launcher.GameList", kListSearchCmd); + _list = new ListWidget(this, "Launcher.GameList", 0, kListSearchCmd); _list->setEditable(false); _list->setNumberingMode(kListNumberingOff); @@ -544,10 +545,10 @@ LauncherDialog::LauncherDialog() updateButtons(); // Create file browser dialog - _browser = new BrowserDialog("Select directory with game data", true); + _browser = new BrowserDialog(_("Select directory with game data"), true); // Create Load dialog - _loadDialog = new SaveLoadChooser("Load game:", "Load"); + _loadDialog = new SaveLoadChooser(_("Load game:"), _("Load")); } void LauncherDialog::selectTarget(const String &target) { @@ -619,8 +620,12 @@ void LauncherDialog::updateListing() { description = g.description(); } - if (description.empty()) - description = "Unknown (target " + iter->_key + ", gameid " + gameid + ")"; + if (description.empty()) { + char tmp[200]; + + snprintf(tmp, 200, "Unknown (target %s, gameid %s)", iter->_key.c_str(), gameid.c_str()); + description = tmp; + } if (!gameid.empty() && !description.empty()) { // Insert the game into the launcher list @@ -652,8 +657,8 @@ void LauncherDialog::addGame() { const bool massAdd = (modifiers & Common::KBD_SHIFT) != 0; if (massAdd) { - MessageDialog alert("Do you really want to run the mass game detector? " - "This could potentially add a huge number of games.", "Yes", "No"); + MessageDialog alert(_("Do you really want to run the mass game detector? " + "This could potentially add a huge number of games."), _("Yes"), _("No")); if (alert.runModal() == GUI::kMessageOK && _browser->runModal() > 0) { MassAddDialog massAddDlg(_browser->getResult()); @@ -700,7 +705,7 @@ void LauncherDialog::addGame() { Common::FSNode dir(_browser->getResult()); Common::FSList files; if (!dir.getChildren(files, Common::FSNode::kListAll)) { - MessageDialog alert("ScummVM couldn't open the specified directory!"); + MessageDialog alert(_("ScummVM couldn't open the specified directory!")); alert.runModal(); return; } @@ -712,7 +717,7 @@ void LauncherDialog::addGame() { int idx; if (candidates.empty()) { // No game was found in the specified directory - MessageDialog alert("ScummVM could not find any game in the specified directory!"); + MessageDialog alert(_("ScummVM could not find any game in the specified directory!")); alert.runModal(); idx = -1; @@ -726,7 +731,7 @@ void LauncherDialog::addGame() { for (idx = 0; idx < (int)candidates.size(); idx++) list.push_back(candidates[idx].description()); - ChooserDialog dialog("Pick the game:"); + ChooserDialog dialog(_("Pick the game:")); dialog.setList(list); idx = dialog.runModal(); } @@ -802,7 +807,7 @@ Common::String addGameToConf(const GameDescriptor &result) { } void LauncherDialog::removeGame(int item) { - MessageDialog alert("Do you really want to remove this game configuration?", "Yes", "No"); + MessageDialog alert(_("Do you really want to remove this game configuration?"), _("Yes"), _("No")); if (alert.runModal() == GUI::kMessageOK) { // Remove the currently selected game from the list @@ -865,11 +870,11 @@ void LauncherDialog::loadGame(int item) { } } else { MessageDialog dialog - ("This game does not support loading games from the launcher.", "OK"); + (_("This game does not support loading games from the launcher."), _("OK")); dialog.runModal(); } } else { - MessageDialog dialog("ScummVM could not find any engine capable of running the selected game!", "OK"); + MessageDialog dialog(_("ScummVM could not find any engine capable of running the selected game!"), _("OK")); dialog.runModal(); } } @@ -981,8 +986,8 @@ void LauncherDialog::updateButtons() { int modifiers = g_system->getEventManager()->getModifierState(); const bool massAdd = (modifiers & Common::KBD_SHIFT) != 0; const char *newAddButtonLabel = massAdd - ? "Mass Add..." - : "Add Game..."; + ? _("Mass Add...") + : _("Add Game..."); if (_addButton->getLabel() != newAddButtonLabel) _addButton->setLabel(newAddButtonLabel); @@ -1029,7 +1034,7 @@ void LauncherDialog::reflowLayout() { } } else { if (!_searchDesc) - _searchDesc = new StaticTextWidget(this, "Launcher.SearchDesc", "Search:"); + _searchDesc = new StaticTextWidget(this, "Launcher.SearchDesc", _("Search:")); if (_searchPic) { removeWidget(_searchPic); diff --git a/gui/massadd.cpp b/gui/massadd.cpp index 266226161a..7a597085c5 100644 --- a/gui/massadd.cpp +++ b/gui/massadd.cpp @@ -27,6 +27,7 @@ #include "common/events.h" #include "common/func.h" #include "common/config-manager.h" +#include "common/translation.h" #include "gui/launcher.h" // For addGameToConf() #include "gui/massadd.h" @@ -75,10 +76,10 @@ MassAddDialog::MassAddDialog(const Common::FSNode &startDir) // new StaticTextWidget(this, "massadddialog_caption", "Mass Add Dialog"); _dirProgressText = new StaticTextWidget(this, "MassAdd.DirProgressText", - "... progress ..."); + _("... progress ...")); _gameProgressText = new StaticTextWidget(this, "MassAdd.GameProgressText", - "... progress ..."); + _("... progress ...")); _dirProgressText->setAlign(Graphics::kTextAlignCenter); _gameProgressText->setAlign(Graphics::kTextAlignCenter); @@ -88,10 +89,10 @@ MassAddDialog::MassAddDialog(const Common::FSNode &startDir) _list->setNumberingMode(kListNumberingOff); _list->setList(l); - _okButton = new ButtonWidget(this, "MassAdd.Ok", "OK", kOkCmd, Common::ASCII_RETURN); + _okButton = new ButtonWidget(this, "MassAdd.Ok", _("OK"), 0, kOkCmd, Common::ASCII_RETURN); _okButton->setEnabled(false); - new ButtonWidget(this, "MassAdd.Cancel", "Cancel", kCancelCmd, Common::ASCII_ESCAPE); + new ButtonWidget(this, "MassAdd.Cancel", _("Cancel"), 0, kCancelCmd, Common::ASCII_ESCAPE); // Build a map from all configured game paths to the targets using them const Common::ConfigManager::DomainMap &domains = ConfMan.getGameDomains(); @@ -240,17 +241,17 @@ void MassAddDialog::handleTickle() { // Enable the OK button _okButton->setEnabled(true); - snprintf(buf, sizeof(buf), "Scan complete!"); + snprintf(buf, sizeof(buf), "%s", _("Scan complete!")); _dirProgressText->setLabel(buf); - snprintf(buf, sizeof(buf), "Discovered %d new games.", _games.size()); + snprintf(buf, sizeof(buf), _("Discovered %d new games."), _games.size()); _gameProgressText->setLabel(buf); } else { - snprintf(buf, sizeof(buf), "Scanned %d directories ...", _dirsScanned); + snprintf(buf, sizeof(buf), _("Scanned %d directories ..."), _dirsScanned); _dirProgressText->setLabel(buf); - snprintf(buf, sizeof(buf), "Discovered %d new games ...", _games.size()); + snprintf(buf, sizeof(buf), _("Discovered %d new games ..."), _games.size()); _gameProgressText->setLabel(buf); } diff --git a/gui/message.cpp b/gui/message.cpp index 12ac3123a4..6406976569 100644 --- a/gui/message.cpp +++ b/gui/message.cpp @@ -89,10 +89,10 @@ MessageDialog::MessageDialog(const Common::String &message, const char *defaultB } if (defaultButton) - new ButtonWidget(this, okButtonPos, _h - buttonHeight - 8, buttonWidth, buttonHeight, defaultButton, kOkCmd, Common::ASCII_RETURN); // Confirm dialog + new ButtonWidget(this, okButtonPos, _h - buttonHeight - 8, buttonWidth, buttonHeight, defaultButton, 0, kOkCmd, Common::ASCII_RETURN); // Confirm dialog if (altButton) - new ButtonWidget(this, cancelButtonPos, _h - buttonHeight - 8, buttonWidth, buttonHeight, altButton, kCancelCmd, Common::ASCII_ESCAPE); // Cancel dialog + new ButtonWidget(this, cancelButtonPos, _h - buttonHeight - 8, buttonWidth, buttonHeight, altButton, 0, kCancelCmd, Common::ASCII_ESCAPE); // Cancel dialog } void MessageDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { diff --git a/gui/options.cpp b/gui/options.cpp index 212e90f9f0..856eb668fa 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -35,10 +35,12 @@ #include "common/fs.h" #include "common/config-manager.h" #include "common/system.h" +#include "common/translation.h" #include "graphics/scaler.h" #include "sound/mididrv.h" +#include "sound/musicplugin.h" #include "sound/mixer.h" #include "sound/fmopl.h" @@ -61,15 +63,21 @@ enum { kChooseThemeCmd = 'chtf' }; +enum { + kSubtitlesSpeech, + kSubtitlesSubs, + kSubtitlesBoth +}; + #ifdef SMALL_SCREEN_DEVICE enum { kChooseKeyMappingCmd = 'chma' }; #endif -static const char *savePeriodLabels[] = { "Never", "every 5 mins", "every 10 mins", "every 15 mins", "every 30 mins", 0 }; +static const char *savePeriodLabels[] = { _s("Never"), _s("every 5 mins"), _s("every 10 mins"), _s("every 15 mins"), _s("every 30 mins"), 0 }; static const int savePeriodValues[] = { 0, 5 * 60, 10 * 60, 15 * 60, 30 * 60, -1 }; -static const char *outputRateLabels[] = { "<default>", "8 kHz", "11kHz", "22 kHz", "44 kHz", "48 kHz", 0 }; +static const char *outputRateLabels[] = { _s("<default>"), _s("8 kHz"), _s("11kHz"), _s("22 kHz"), _s("44 kHz"), _s("48 kHz"), 0 }; static const int outputRateValues[] = { 0, 8000, 11025, 22050, 44100, 48000, -1 }; @@ -84,18 +92,6 @@ OptionsDialog::OptionsDialog(const Common::String &domain, const Common::String init(); } -const char *OptionsDialog::_subModeDesc[] = { - "Speech Only", - "Speech and Subtitles", - "Subtitles Only" -}; - -const char *OptionsDialog::_lowresSubModeDesc[] = { - "Speech Only", - "Speech & Subs", - "Subtitles Only" -}; - void OptionsDialog::init() { _enableGraphicSettings = false; _gfxPopUp = 0; @@ -104,6 +100,8 @@ void OptionsDialog::init() { _aspectCheckbox = 0; _enableAudioSettings = false; _midiPopUp = 0; + _mt32DevicePopUp = 0; + _gmDevicePopUp = 0; _oplPopUp = 0; _outputRatePopUp = 0; _enableMIDISettings = false; @@ -122,15 +120,20 @@ void OptionsDialog::init() { _speechVolumeLabel = 0; _muteCheckbox = 0; _subToggleDesc = 0; - _subToggleButton = 0; + _subToggleGroup = 0; + _subToggleSubOnly = 0; + _subToggleSpeechOnly = 0; + _subToggleSubBoth = 0; _subSpeedDesc = 0; _subSpeedSlider = 0; _subSpeedLabel = 0; // Retrieve game GUI options _guioptions = 0; - if (ConfMan.hasKey("guioptions", _domain)) - _guioptions = parseGameGUIOptions(ConfMan.get("guioptions", _domain)); + if (ConfMan.hasKey("guioptions", _domain)) { + _guioptionsString = ConfMan.get("guioptions", _domain); + _guioptions = parseGameGUIOptions(_guioptionsString); + } } void OptionsDialog::open() { @@ -141,8 +144,10 @@ void OptionsDialog::open() { // Retrieve game GUI options _guioptions = 0; - if (ConfMan.hasKey("guioptions", _domain)) - _guioptions = parseGameGUIOptions(ConfMan.get("guioptions", _domain)); + if (ConfMan.hasKey("guioptions", _domain)) { + _guioptionsString = ConfMan.get("guioptions", _domain); + _guioptions = parseGameGUIOptions(_guioptionsString); + } // Graphic options if (_fullscreenCheckbox) { @@ -189,10 +194,25 @@ void OptionsDialog::open() { } // Audio options - if (_midiPopUp) { - // Music driver - MidiDriverType id = MidiDriver::parseMusicDriver(ConfMan.get("music_driver", _domain)); - _midiPopUp->setSelectedTag(id); + if (!loadMusicDeviceSetting(_midiPopUp, "music_driver")) + _midiPopUp->setSelected(0); + + if (!loadMusicDeviceSetting(_mt32DevicePopUp, "mt32_device")) { + if (_domain.equals(Common::ConfigManager::kApplicationDomain)) { + if (!loadMusicDeviceSetting(_mt32DevicePopUp, Common::String(), MT_MT32)) + _mt32DevicePopUp->setSelected(0); + } else { + _mt32DevicePopUp->setSelected(0); + } + } + + if (!loadMusicDeviceSetting(_gmDevicePopUp, "gm_device")) { + if (_domain.equals(Common::ConfigManager::kApplicationDomain)) { + if (!loadMusicDeviceSetting(_gmDevicePopUp, Common::String(), MT_GM)) + _gmDevicePopUp->setSelected(0); + } else { + _gmDevicePopUp->setSelected(0); + } } if (_oplPopUp) { @@ -222,7 +242,7 @@ void OptionsDialog::open() { Common::String soundFont(ConfMan.get("soundfont", _domain)); if (soundFont.empty() || !ConfMan.hasKey("soundfont", _domain)) { - _soundFont->setLabel("None"); + _soundFont->setLabel(_("None")); _soundFontClearButton->setEnabled(false); } else { _soundFont->setLabel(soundFont); @@ -263,11 +283,12 @@ void OptionsDialog::open() { } // Subtitle options - if (_subToggleButton) { - int speed; int sliderMaxValue = _subSpeedSlider->getMaxValue(); + if (_subToggleGroup) { + int speed; + int sliderMaxValue = _subSpeedSlider->getMaxValue(); - _subMode = getSubtitleMode(ConfMan.getBool("subtitles", _domain), ConfMan.getBool("speech_mute", _domain)); - _subToggleButton->setLabel(_subModeDesc[_subMode]); + int subMode = getSubtitleMode(ConfMan.getBool("subtitles", _domain), ConfMan.getBool("speech_mute", _domain)); + _subToggleGroup->setValue(subMode); // Engines that reuse the subtitle speed widget set their own max value. // Scale the config value accordingly (see addSubtitleControls) @@ -331,15 +352,13 @@ void OptionsDialog::close() { // Audio options if (_midiPopUp) { if (_enableAudioSettings) { - const MidiDriverDescription *md = MidiDriver::getAvailableMidiDrivers(); - while (md->name && md->id != (int)_midiPopUp->getSelectedTag()) - md++; - if (md->name) - ConfMan.set("music_driver", md->name, _domain); - else - ConfMan.removeKey("music_driver", _domain); + saveMusicDeviceSetting(_midiPopUp, "music_driver"); + saveMusicDeviceSetting(_mt32DevicePopUp, "mt32_device"); + saveMusicDeviceSetting(_gmDevicePopUp, "gm_device"); } else { ConfMan.removeKey("music_driver", _domain); + ConfMan.removeKey("mt32_device", _domain); + ConfMan.removeKey("gm_device", _domain); } } @@ -378,7 +397,7 @@ void OptionsDialog::close() { ConfMan.setInt("midi_gain", _midiGainSlider->getValue(), _domain); Common::String soundFont(_soundFont->getLabel()); - if (!soundFont.empty() && (soundFont != "None")) + if (!soundFont.empty() && (soundFont != _("None"))) ConfMan.set("soundfont", soundFont, _domain); else ConfMan.removeKey("soundfont", _domain); @@ -392,21 +411,21 @@ void OptionsDialog::close() { } // Subtitle options - if (_subToggleButton) { + if (_subToggleGroup) { if (_enableSubtitleSettings) { bool subtitles, speech_mute; int talkspeed; int sliderMaxValue = _subSpeedSlider->getMaxValue(); - switch (_subMode) { - case 0: + switch (_subToggleGroup->getValue()) { + case kSubtitlesSpeech: subtitles = speech_mute = false; break; - case 1: + case kSubtitlesBoth: subtitles = true; speech_mute = false; break; - case 2: + case kSubtitlesSubs: default: subtitles = speech_mute = true; break; @@ -459,24 +478,12 @@ void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data // 'true' because if control is disabled then event do not pass setVolumeSettingsState(true); break; - case kSubtitleToggle: - if (_subMode < 2) - _subMode++; - else - _subMode = 0; - - _subToggleButton->setLabel(g_system->getOverlayWidth() > 320 ? _subModeDesc[_subMode] : _lowresSubModeDesc[_subMode]); - _subToggleButton->draw(); - _subSpeedDesc->draw(); - _subSpeedSlider->draw(); - _subSpeedLabel->draw(); - break; case kSubtitleSpeedChanged: _subSpeedLabel->setValue(_subSpeedSlider->getValue()); _subSpeedLabel->draw(); break; case kClearSoundFontCmd: - _soundFont->setLabel("None"); + _soundFont->setLabel(_("None")); _soundFontClearButton->setEnabled(false); draw(); break; @@ -504,11 +511,24 @@ void OptionsDialog::setGraphicSettingsState(bool enabled) { void OptionsDialog::setAudioSettingsState(bool enabled) { _enableAudioSettings = enabled; - _midiPopUpDesc->setEnabled(enabled); _midiPopUp->setEnabled(enabled); - _oplPopUpDesc->setEnabled(enabled); - _oplPopUp->setEnabled(enabled); + _mt32DevicePopUpDesc->setEnabled(_domain.equals(Common::ConfigManager::kApplicationDomain) ? enabled : false); + _mt32DevicePopUp->setEnabled(_domain.equals(Common::ConfigManager::kApplicationDomain) ? enabled : false); + _gmDevicePopUpDesc->setEnabled(_domain.equals(Common::ConfigManager::kApplicationDomain) ? enabled : false); + _gmDevicePopUp->setEnabled(_domain.equals(Common::ConfigManager::kApplicationDomain) ? enabled : false); + + uint32 allFlags = MidiDriver::musicType2GUIO((uint32)-1); + + if (_domain != Common::ConfigManager::kApplicationDomain && // global dialog + (_guioptions & allFlags) && // No flags are specified + !(_guioptions & Common::GUIO_MIDIADLIB)) { + _oplPopUpDesc->setEnabled(false); + _oplPopUp->setEnabled(false); + } else { + _oplPopUpDesc->setEnabled(enabled); + _oplPopUp->setEnabled(enabled); + } _outputRatePopUpDesc->setEnabled(enabled); _outputRatePopUp->setEnabled(enabled); } @@ -522,7 +542,7 @@ void OptionsDialog::setMIDISettingsState(bool enabled) { _soundFontButton->setEnabled(enabled); _soundFont->setEnabled(enabled); - if (enabled && !_soundFont->getLabel().empty() && (_soundFont->getLabel() != "None")) + if (enabled && !_soundFont->getLabel().empty() && (_soundFont->getLabel() != _("None"))) _soundFontClearButton->setEnabled(enabled); else _soundFontClearButton->setEnabled(false); @@ -575,7 +595,7 @@ void OptionsDialog::setSubtitleSettingsState(bool enabled) { if ((_guioptions & Common::GUIO_NOSUBTITLES) || (_guioptions & Common::GUIO_NOSPEECH)) ena = false; - _subToggleButton->setEnabled(ena); + _subToggleGroup->setEnabled(ena); _subToggleDesc->setEnabled(ena); ena = enabled; @@ -591,64 +611,90 @@ void OptionsDialog::addGraphicControls(GuiObject *boss, const Common::String &pr const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes(); // The GFX mode popup - _gfxPopUpDesc = new StaticTextWidget(boss, prefix + "grModePopupDesc", "Graphics mode:"); + _gfxPopUpDesc = new StaticTextWidget(boss, prefix + "grModePopupDesc", _("Graphics mode:")); _gfxPopUp = new PopUpWidget(boss, prefix + "grModePopup"); - _gfxPopUp->appendEntry("<default>"); + _gfxPopUp->appendEntry(_("<default>")); _gfxPopUp->appendEntry(""); while (gm->name) { - _gfxPopUp->appendEntry(gm->description, gm->id); + _gfxPopUp->appendEntry(_(gm->description), gm->id); gm++; } // RenderMode popup - _renderModePopUpDesc = new StaticTextWidget(boss, prefix + "grRenderPopupDesc", "Render mode:"); - _renderModePopUp = new PopUpWidget(boss, prefix + "grRenderPopup"); - _renderModePopUp->appendEntry("<default>", Common::kRenderDefault); + _renderModePopUpDesc = new StaticTextWidget(boss, prefix + "grRenderPopupDesc", _("Render mode:"), _("Special dithering modes supported by some games")); + _renderModePopUp = new PopUpWidget(boss, prefix + "grRenderPopup", _("Special dithering modes supported by some games")); + _renderModePopUp->appendEntry(_("<default>"), Common::kRenderDefault); _renderModePopUp->appendEntry(""); const Common::RenderModeDescription *rm = Common::g_renderModes; for (; rm->code; ++rm) { - _renderModePopUp->appendEntry(rm->description, rm->id); + _renderModePopUp->appendEntry(_(rm->description), rm->id); } // Fullscreen checkbox - _fullscreenCheckbox = new CheckboxWidget(boss, prefix + "grFullscreenCheckbox", "Fullscreen mode", 0, 0); + _fullscreenCheckbox = new CheckboxWidget(boss, prefix + "grFullscreenCheckbox", _("Fullscreen mode")); // Aspect ratio checkbox - _aspectCheckbox = new CheckboxWidget(boss, prefix + "grAspectCheckbox", "Aspect ratio correction", 0, 0); + _aspectCheckbox = new CheckboxWidget(boss, prefix + "grAspectCheckbox", _("Aspect ratio correction"), _("Correct aspect ratio for 320x200 games")); _enableGraphicSettings = true; } void OptionsDialog::addAudioControls(GuiObject *boss, const Common::String &prefix) { // The MIDI mode popup & a label - _midiPopUpDesc = new StaticTextWidget(boss, prefix + "auMidiPopupDesc", "Music driver:"); - _midiPopUp = new PopUpWidget(boss, prefix + "auMidiPopup"); + _midiPopUpDesc = new StaticTextWidget(boss, prefix + "auMidiPopupDesc", _domain == Common::ConfigManager::kApplicationDomain ? _("Preferred Device:") : _("Music Device:"), _domain == Common::ConfigManager::kApplicationDomain ? _("Specifies preferred sound device or sound card emulator") : _("Specifies output sound device or sound card emulator")); + _midiPopUp = new PopUpWidget(boss, prefix + "auMidiPopup", _("Specifies output sound device or sound card emulator")); + + _mt32DevicePopUpDesc = new StaticTextWidget(boss, prefix + "auPrefMt32PopupDesc", _("MT-32 Device:"), _("Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output")); + _mt32DevicePopUp = new PopUpWidget(boss, prefix + "auPrefMt32Popup"); + _gmDevicePopUpDesc = new StaticTextWidget(boss, prefix + "auPrefGmPopupDesc", _("GM Device:"), _("Specifies default sound device for General MIDI output")); + _gmDevicePopUp = new PopUpWidget(boss, prefix + "auPrefGmPopup"); // Populate it - const MidiDriverDescription *md = MidiDriver::getAvailableMidiDrivers(); - while (md->name) { - _midiPopUp->appendEntry(md->description, md->id); - md++; + uint32 allFlags = MidiDriver::musicType2GUIO((uint32)-1); + + const MusicPlugin::List p = MusicMan.getPlugins(); + for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { + MusicDevices i = (**m)->getDevices(); + for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { + if ((_domain == Common::ConfigManager::kApplicationDomain && d->getMusicType() != MT_TOWNS) // global dialog - skip useless FM-Towns option there + || (_domain != Common::ConfigManager::kApplicationDomain && !(_guioptions & allFlags)) // No flags are specified + || _guioptions & (MidiDriver::musicType2GUIO(d->getMusicType())) // flag is present + || d->getMusicDriverId() == "auto" || d->getMusicDriverId() == "null") // always add default and null device + _midiPopUp->appendEntry(d->getCompleteName(), d->getHandle()); + + if (d->getMusicType() >= MT_GM || d->getMusicDriverId() == "auto") { + _mt32DevicePopUp->appendEntry(d->getCompleteName(), d->getHandle()); + if (d->getMusicType() != MT_MT32) + _gmDevicePopUp->appendEntry(d->getCompleteName(), d->getHandle()); + } + } + } + + if (!_domain.equals(Common::ConfigManager::kApplicationDomain)) { + _mt32DevicePopUpDesc->setEnabled(false); + _mt32DevicePopUp->setEnabled(false); + _gmDevicePopUpDesc->setEnabled(false); + _gmDevicePopUp->setEnabled(false); } // The OPL emulator popup & a label - _oplPopUpDesc = new StaticTextWidget(boss, prefix + "auOPLPopupDesc", "AdLib emulator:"); - _oplPopUp = new PopUpWidget(boss, prefix + "auOPLPopup"); + _oplPopUpDesc = new StaticTextWidget(boss, prefix + "auOPLPopupDesc", _("AdLib emulator:"), _("AdLib is used for music in many games")); + _oplPopUp = new PopUpWidget(boss, prefix + "auOPLPopup", _("AdLib is used for music in many games")); // Populate it const OPL::Config::EmulatorDescription *ed = OPL::Config::getAvailable(); while (ed->name) { - _oplPopUp->appendEntry(ed->description, ed->id); + _oplPopUp->appendEntry(_(ed->description), ed->id); ++ed; } // Sample rate settings - _outputRatePopUpDesc = new StaticTextWidget(boss, prefix + "auSampleRatePopupDesc", "Output rate:"); - _outputRatePopUp = new PopUpWidget(boss, prefix + "auSampleRatePopup"); + _outputRatePopUpDesc = new StaticTextWidget(boss, prefix + "auSampleRatePopupDesc", _("Output rate:"), _("Higher value specifies better sound quality but may be not supported by your soundcard")); + _outputRatePopUp = new PopUpWidget(boss, prefix + "auSampleRatePopup", _("Higher value specifies better sound quality but may be not supported by your soundcard")); for (int i = 0; outputRateLabels[i]; i++) { - _outputRatePopUp->appendEntry(outputRateLabels[i], outputRateValues[i]); + _outputRatePopUp->appendEntry(_(outputRateLabels[i]), outputRateValues[i]); } _enableAudioSettings = true; @@ -656,22 +702,22 @@ void OptionsDialog::addAudioControls(GuiObject *boss, const Common::String &pref void OptionsDialog::addMIDIControls(GuiObject *boss, const Common::String &prefix) { // SoundFont - _soundFontButton = new ButtonWidget(boss, prefix + "mcFontButton", "SoundFont:", kChooseSoundFontCmd, 0); - _soundFont = new StaticTextWidget(boss, prefix + "mcFontPath", "None"); - _soundFontClearButton = new ButtonWidget(boss, prefix + "mcFontClearButton", "C", kClearSoundFontCmd, 0); + _soundFontButton = new ButtonWidget(boss, prefix + "mcFontButton", _("SoundFont:"), _("SoundFont is supported by some audio cards, Fluidsynth and Timidity"), kChooseSoundFontCmd); + _soundFont = new StaticTextWidget(boss, prefix + "mcFontPath", _("None"), _("SoundFont is supported by some audio cards, Fluidsynth and Timidity")); + _soundFontClearButton = new ButtonWidget(boss, prefix + "mcFontClearButton", "C", _("Clear value"), kClearSoundFontCmd); // Multi midi setting - _multiMidiCheckbox = new CheckboxWidget(boss, prefix + "mcMixedCheckbox", "Mixed AdLib/MIDI mode", 0, 0); + _multiMidiCheckbox = new CheckboxWidget(boss, prefix + "mcMixedCheckbox", _("Mixed AdLib/MIDI mode"), _("Use both MIDI and AdLib sound generation")); // Native mt32 setting - _mt32Checkbox = new CheckboxWidget(boss, prefix + "mcMt32Checkbox", "True Roland MT-32 (disable GM emulation)", 0, 0); + _mt32Checkbox = new CheckboxWidget(boss, prefix + "mcMt32Checkbox", _("True Roland MT-32 (disable GM emulation)"), _("Check if you want to use your real hardware Roland-compatible sound device connected to your computer")); // GS Extensions setting - _enableGSCheckbox = new CheckboxWidget(boss, prefix + "mcGSCheckbox", "Enable Roland GS Mode", 0, 0); + _enableGSCheckbox = new CheckboxWidget(boss, prefix + "mcGSCheckbox", _("Enable Roland GS Mode"), _("Turns off General MIDI mapping for games with Roland MT-32 soundtrack")); // MIDI gain setting (FluidSynth uses this) - _midiGainDesc = new StaticTextWidget(boss, prefix + "mcMidiGainText", "MIDI gain:"); - _midiGainSlider = new SliderWidget(boss, prefix + "mcMidiGainSlider", kMidiGainChanged); + _midiGainDesc = new StaticTextWidget(boss, prefix + "mcMidiGainText", _("MIDI gain:")); + _midiGainSlider = new SliderWidget(boss, prefix + "mcMidiGainSlider", 0, kMidiGainChanged); _midiGainSlider->setMinValue(0); _midiGainSlider->setMaxValue(1000); _midiGainLabel = new StaticTextWidget(boss, prefix + "mcMidiGainLabel", "1.00"); @@ -683,12 +729,25 @@ void OptionsDialog::addMIDIControls(GuiObject *boss, const Common::String &prefi // make use of the widgets. The launcher range is 0-255. SCUMM's 0-9 void OptionsDialog::addSubtitleControls(GuiObject *boss, const Common::String &prefix, int maxSliderVal) { - _subToggleDesc = new StaticTextWidget(boss, prefix + "subToggleDesc", "Text and Speech:"); - _subToggleButton = new ButtonWidget(boss, prefix + "subToggleButton", "", kSubtitleToggle, 0); + _subToggleDesc = new StaticTextWidget(boss, prefix + "subToggleDesc", _("Text and Speech:")); + + if (g_system->getOverlayWidth() > 320) { + _subToggleGroup = new RadiobuttonGroup(boss, kSubtitleToggle); + + _subToggleSpeechOnly = new RadiobuttonWidget(boss, prefix + "subToggleSpeechOnly", _subToggleGroup, kSubtitlesSpeech, _("Speech")); + _subToggleSubOnly = new RadiobuttonWidget(boss, prefix + "subToggleSubOnly", _subToggleGroup, kSubtitlesSubs, _("Subtitles")); + _subToggleSubBoth = new RadiobuttonWidget(boss, prefix + "subToggleSubBoth", _subToggleGroup, kSubtitlesBoth, _("Both")); + } else { + _subToggleGroup = new RadiobuttonGroup(boss, kSubtitleToggle); + + _subToggleSpeechOnly = new RadiobuttonWidget(boss, prefix + "subToggleSpeechOnly", _subToggleGroup, kSubtitlesSpeech, _("Spch"), _("Speech")); + _subToggleSubOnly = new RadiobuttonWidget(boss, prefix + "subToggleSubOnly", _subToggleGroup, kSubtitlesSubs, _("Subs"), _("Subtitles")); + _subToggleSubBoth = new RadiobuttonWidget(boss, prefix + "subToggleSubBoth", _subToggleGroup, kSubtitlesBoth, _("Both"), _("Show subtitles and play speech")); + } // Subtitle speed - _subSpeedDesc = new StaticTextWidget(boss, prefix + "subSubtitleSpeedDesc", "Subtitle speed:"); - _subSpeedSlider = new SliderWidget(boss, prefix + "subSubtitleSpeedSlider", kSubtitleSpeedChanged); + _subSpeedDesc = new StaticTextWidget(boss, prefix + "subSubtitleSpeedDesc", _("Subtitle speed:")); + _subSpeedSlider = new SliderWidget(boss, prefix + "subSubtitleSpeedSlider", 0, kSubtitleSpeedChanged); _subSpeedLabel = new StaticTextWidget(boss, prefix + "subSubtitleSpeedLabel", "100%"); _subSpeedSlider->setMinValue(0); _subSpeedSlider->setMaxValue(maxSliderVal); _subSpeedLabel->setFlags(WIDGET_CLEARBG); @@ -699,25 +758,25 @@ void OptionsDialog::addSubtitleControls(GuiObject *boss, const Common::String &p void OptionsDialog::addVolumeControls(GuiObject *boss, const Common::String &prefix) { // Volume controllers - _musicVolumeDesc = new StaticTextWidget(boss, prefix + "vcMusicText", "Music volume:"); - _musicVolumeSlider = new SliderWidget(boss, prefix + "vcMusicSlider", kMusicVolumeChanged); + _musicVolumeDesc = new StaticTextWidget(boss, prefix + "vcMusicText", _("Music volume:")); + _musicVolumeSlider = new SliderWidget(boss, prefix + "vcMusicSlider", 0, kMusicVolumeChanged); _musicVolumeLabel = new StaticTextWidget(boss, prefix + "vcMusicLabel", "100%"); _musicVolumeSlider->setMinValue(0); _musicVolumeSlider->setMaxValue(Audio::Mixer::kMaxMixerVolume); _musicVolumeLabel->setFlags(WIDGET_CLEARBG); - _muteCheckbox = new CheckboxWidget(boss, prefix + "vcMuteCheckbox", "Mute All", kMuteAllChanged, 0); + _muteCheckbox = new CheckboxWidget(boss, prefix + "vcMuteCheckbox", _("Mute All"), 0, kMuteAllChanged); - _sfxVolumeDesc = new StaticTextWidget(boss, prefix + "vcSfxText", "SFX volume:"); - _sfxVolumeSlider = new SliderWidget(boss, prefix + "vcSfxSlider", kSfxVolumeChanged); + _sfxVolumeDesc = new StaticTextWidget(boss, prefix + "vcSfxText", _("SFX volume:"), _("Special sound effects volume")); + _sfxVolumeSlider = new SliderWidget(boss, prefix + "vcSfxSlider", _("Special sound effects volume"), kSfxVolumeChanged); _sfxVolumeLabel = new StaticTextWidget(boss, prefix + "vcSfxLabel", "100%"); _sfxVolumeSlider->setMinValue(0); _sfxVolumeSlider->setMaxValue(Audio::Mixer::kMaxMixerVolume); _sfxVolumeLabel->setFlags(WIDGET_CLEARBG); - _speechVolumeDesc = new StaticTextWidget(boss, prefix + "vcSpeechText" , "Speech volume:"); - _speechVolumeSlider = new SliderWidget(boss, prefix + "vcSpeechSlider", kSpeechVolumeChanged); + _speechVolumeDesc = new StaticTextWidget(boss, prefix + "vcSpeechText" , _("Speech volume:")); + _speechVolumeSlider = new SliderWidget(boss, prefix + "vcSpeechSlider", 0, kSpeechVolumeChanged); _speechVolumeLabel = new StaticTextWidget(boss, prefix + "vcSpeechLabel", "100%"); _speechVolumeSlider->setMinValue(0); _speechVolumeSlider->setMaxValue(Audio::Mixer::kMaxMixerVolume); @@ -726,26 +785,69 @@ void OptionsDialog::addVolumeControls(GuiObject *boss, const Common::String &pre _enableVolumeSettings = true; } +bool OptionsDialog::loadMusicDeviceSetting(PopUpWidget *popup, Common::String setting, MusicType preferredType) { + if (!popup || !popup->isEnabled()) + return true; + + if (_domain != Common::ConfigManager::kApplicationDomain || ConfMan.hasKey(setting, _domain) || preferredType) { + const Common::String drv = ConfMan.get(setting, (_domain != Common::ConfigManager::kApplicationDomain && !ConfMan.hasKey(setting, _domain)) ? Common::ConfigManager::kApplicationDomain : _domain); + const MusicPlugin::List p = MusicMan.getPlugins(); + + for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { + MusicDevices i = (**m)->getDevices(); + for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { + if (setting.empty() ? (preferredType == d->getMusicType()) : (drv == d->getCompleteId())) { + popup->setSelectedTag(d->getHandle()); + return popup->getSelected() == -1 ? false : true; + } + } + } + } + + return false; +} + +void OptionsDialog::saveMusicDeviceSetting(PopUpWidget *popup, Common::String setting) { + if (!popup || !_enableAudioSettings) + return; + + const MusicPlugin::List p = MusicMan.getPlugins(); + bool found = false; + for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end() && !found; ++m) { + MusicDevices i = (**m)->getDevices(); + for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { + if (d->getHandle() == popup->getSelectedTag()) { + ConfMan.set(setting, d->getCompleteId(), _domain); + found = true; + break; + } + } + } + + if (!found) + ConfMan.removeKey(setting, _domain); +} + int OptionsDialog::getSubtitleMode(bool subtitles, bool speech_mute) { if (_guioptions & Common::GUIO_NOSUBTITLES) - return 0; // Speech only + return kSubtitlesSpeech; // Speech only if (_guioptions & Common::GUIO_NOSPEECH) - return 2; // Subtitles only + return kSubtitlesSubs; // Subtitles only if (!subtitles && !speech_mute) // Speech only - return 0; + return kSubtitlesSpeech; else if (subtitles && !speech_mute) // Speech and subtitles - return 1; + return kSubtitlesBoth; else if (subtitles && speech_mute) // Subtitles only - return 2; + return kSubtitlesSubs; else warning("Wrong configuration: Both subtitles and speech are off. Assuming subtitles only"); - return 2; + return kSubtitlesSubs; } void OptionsDialog::reflowLayout() { if (_graphicsTabId != -1 && _tabWidget) - _tabWidget->setTabTitle(_graphicsTabId, g_system->getOverlayWidth() > 320 ? "Graphics" : "GFX"); + _tabWidget->setTabTitle(_graphicsTabId, g_system->getOverlayWidth() > 320 ? _("Graphics") : _("GFX")); Dialog::reflowLayout(); } @@ -762,17 +864,17 @@ GlobalOptionsDialog::GlobalOptionsDialog() // // 1) The graphics tab // - _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? "Graphics" : "GFX"); + _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? _("Graphics") : _("GFX")); addGraphicControls(tab, "GlobalOptions_Graphics."); // // 2) The audio tab // - tab->addTab("Audio"); + tab->addTab(_("Audio")); addAudioControls(tab, "GlobalOptions_Audio."); addSubtitleControls(tab, "GlobalOptions_Audio."); - tab->addTab("Volume"); + tab->addTab(_("Volume")); addVolumeControls(tab, "GlobalOptions_Volume."); // TODO: cd drive setting @@ -780,67 +882,95 @@ GlobalOptionsDialog::GlobalOptionsDialog() // // 3) The MIDI tab // - tab->addTab("MIDI"); + tab->addTab(_("MIDI")); addMIDIControls(tab, "GlobalOptions_MIDI."); // // 4) The miscellaneous tab // - tab->addTab("Paths"); + tab->addTab(_("Paths")); #if !( defined(__DC__) || defined(__GP32__) ) // These two buttons have to be extra wide, or the text will be // truncated in the small version of the GUI. // Save game path - new ButtonWidget(tab, "GlobalOptions_Paths.SaveButton", "Save Path: ", kChooseSaveDirCmd, 0); - _savePath = new StaticTextWidget(tab, "GlobalOptions_Paths.SavePath", "/foo/bar"); + new ButtonWidget(tab, "GlobalOptions_Paths.SaveButton", _("Save Path: "), _("Specifies where your savegames are put"), kChooseSaveDirCmd); + _savePath = new StaticTextWidget(tab, "GlobalOptions_Paths.SavePath", "/foo/bar", _("Specifies where your savegames are put")); - new ButtonWidget(tab, "GlobalOptions_Paths.ThemeButton", "Theme Path:", kChooseThemeDirCmd, 0); - _themePath = new StaticTextWidget(tab, "GlobalOptions_Paths.ThemePath", "None"); + new ButtonWidget(tab, "GlobalOptions_Paths.ThemeButton", _("Theme Path:"), 0, kChooseThemeDirCmd); + _themePath = new StaticTextWidget(tab, "GlobalOptions_Paths.ThemePath", _("None")); - new ButtonWidget(tab, "GlobalOptions_Paths.ExtraButton", "Extra Path:", kChooseExtraDirCmd, 0); - _extraPath = new StaticTextWidget(tab, "GlobalOptions_Paths.ExtraPath", "None"); + new ButtonWidget(tab, "GlobalOptions_Paths.ExtraButton", _("Extra Path:"), _("Specifies path to additional data used by all games or ScummVM"), kChooseExtraDirCmd); + _extraPath = new StaticTextWidget(tab, "GlobalOptions_Paths.ExtraPath", _("None"), _("Specifies path to additional data used by all games or ScummVM")); #ifdef DYNAMIC_MODULES - new ButtonWidget(tab, "GlobalOptions_Paths.PluginsButton", "Plugins Path:", kChoosePluginsDirCmd, 0); - _pluginsPath = new StaticTextWidget(tab, "GlobalOptions_Paths.PluginsPath", "None"); + new ButtonWidget(tab, "GlobalOptions_Paths.PluginsButton", _("Plugins Path:"), 0, kChoosePluginsDirCmd); + _pluginsPath = new StaticTextWidget(tab, "GlobalOptions_Paths.PluginsPath", _("None")); #endif #endif - tab->addTab("Misc"); + tab->addTab(_("Misc")); - new ButtonWidget(tab, "GlobalOptions_Misc.ThemeButton", "Theme:", kChooseThemeCmd, 0); + new ButtonWidget(tab, "GlobalOptions_Misc.ThemeButton", _("Theme:"), 0, kChooseThemeCmd); _curTheme = new StaticTextWidget(tab, "GlobalOptions_Misc.CurTheme", g_gui.theme()->getThemeName()); - _rendererPopUpDesc = new StaticTextWidget(tab, "GlobalOptions_Misc.RendererPopupDesc", "GUI Renderer:"); + _rendererPopUpDesc = new StaticTextWidget(tab, "GlobalOptions_Misc.RendererPopupDesc", _("GUI Renderer:")); _rendererPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.RendererPopup"); for (uint i = 1; i < GUI::ThemeEngine::_rendererModesSize; ++i) - _rendererPopUp->appendEntry(GUI::ThemeEngine::_rendererModes[i].name, GUI::ThemeEngine::_rendererModes[i].mode); + _rendererPopUp->appendEntry(_(GUI::ThemeEngine::_rendererModes[i].name), GUI::ThemeEngine::_rendererModes[i].mode); - _autosavePeriodPopUpDesc = new StaticTextWidget(tab, "GlobalOptions_Misc.AutosavePeriodPopupDesc", "Autosave:"); + _autosavePeriodPopUpDesc = new StaticTextWidget(tab, "GlobalOptions_Misc.AutosavePeriodPopupDesc", _("Autosave:")); _autosavePeriodPopUp = new PopUpWidget(tab, "GlobalOptions_Misc.AutosavePeriodPopup"); for (int i = 0; savePeriodLabels[i]; i++) { - _autosavePeriodPopUp->appendEntry(savePeriodLabels[i], savePeriodValues[i]); + _autosavePeriodPopUp->appendEntry(_(savePeriodLabels[i]), savePeriodValues[i]); } #ifdef SMALL_SCREEN_DEVICE - new ButtonWidget(tab, "GlobalOptions_Misc.KeysButton", "Keys", kChooseKeyMappingCmd, 0); + new ButtonWidget(tab, "GlobalOptions_Misc.KeysButton", _("Keys"), 0, kChooseKeyMappingCmd); #endif // TODO: joystick setting +#ifdef USE_TRANSLATION + _guiLanguagePopUpDesc = new StaticTextWidget(tab, "GlobalOptions_Misc.GuiLanguagePopupDesc", _("GUI Language:"), _("Language of ScummVM GUI")); + _guiLanguagePopUp = new PopUpWidget(tab, "GlobalOptions_Misc.GuiLanguagePopup"); +#ifdef USE_DETECTLANG + _guiLanguagePopUp->appendEntry(_("<default>"), Common::kTranslationAutodetectId); +#endif // USE_DETECTLANG + _guiLanguagePopUp->appendEntry(_("English"), Common::kTranslationBuiltinId); + _guiLanguagePopUp->appendEntry("", 0); + Common::TLangArray languages = TransMan.getSupportedLanguages(); + Common::TLangArray::iterator lang = languages.begin(); + while (lang != languages.end()) { + _guiLanguagePopUp->appendEntry(lang->name, lang->id); + lang++; + } + + // Select the currently configured language or default/English if + // nothing is specified. + if (ConfMan.hasKey("gui_language")) + _guiLanguagePopUp->setSelectedTag(TransMan.parseLanguage(ConfMan.get("gui_language"))); + else +#ifdef USE_DETECTLANG + _guiLanguagePopUp->setSelectedTag(Common::kTranslationAutodetectId); +#else // !USE_DETECTLANG + _guiLanguagePopUp->setSelectedTag(Common::kTranslationBuiltinId); +#endif // USE_DETECTLANG + +#endif // USE_TRANSLATION + // Activate the first tab tab->setActiveTab(0); _tabWidget = tab; // Add OK & Cancel buttons - new ButtonWidget(this, "GlobalOptions.Cancel", "Cancel", kCloseCmd, 0); - new ButtonWidget(this, "GlobalOptions.Ok", "OK", kOKCmd, 0); + new ButtonWidget(this, "GlobalOptions.Cancel", _("Cancel"), 0, kCloseCmd); + new ButtonWidget(this, "GlobalOptions.Ok", _("OK"), 0, kOKCmd); #ifdef SMALL_SCREEN_DEVICE _keysDialog = new KeysDialog(); @@ -863,19 +993,19 @@ void GlobalOptionsDialog::open() { Common::String extraPath(ConfMan.get("extrapath", _domain)); if (savePath.empty() || !ConfMan.hasKey("savepath", _domain)) { - _savePath->setLabel("None"); + _savePath->setLabel(_("None")); } else { _savePath->setLabel(savePath); } if (themePath.empty() || !ConfMan.hasKey("themepath", _domain)) { - _themePath->setLabel("None"); + _themePath->setLabel(_("None")); } else { _themePath->setLabel(themePath); } if (extraPath.empty() || !ConfMan.hasKey("extrapath", _domain)) { - _extraPath->setLabel("None"); + _extraPath->setLabel(_("None")); } else { _extraPath->setLabel(extraPath); } @@ -883,7 +1013,7 @@ void GlobalOptionsDialog::open() { #ifdef DYNAMIC_MODULES Common::String pluginsPath(ConfMan.get("pluginspath", _domain)); if (pluginsPath.empty() || !ConfMan.hasKey("pluginspath", _domain)) { - _pluginsPath->setLabel("None"); + _pluginsPath->setLabel(_("None")); } else { _pluginsPath->setLabel(pluginsPath); } @@ -907,24 +1037,24 @@ void GlobalOptionsDialog::open() { void GlobalOptionsDialog::close() { if (getResult()) { Common::String savePath(_savePath->getLabel()); - if (!savePath.empty() && (savePath != "None")) + if (!savePath.empty() && (savePath != _("None"))) ConfMan.set("savepath", savePath, _domain); Common::String themePath(_themePath->getLabel()); - if (!themePath.empty() && (themePath != "None")) + if (!themePath.empty() && (themePath != _("None"))) ConfMan.set("themepath", themePath, _domain); else ConfMan.removeKey("themepath", _domain); Common::String extraPath(_extraPath->getLabel()); - if (!extraPath.empty() && (extraPath != "None")) + if (!extraPath.empty() && (extraPath != _("None"))) ConfMan.set("extrapath", extraPath, _domain); else ConfMan.removeKey("extrapath", _domain); #ifdef DYNAMIC_MODULES Common::String pluginsPath(_pluginsPath->getLabel()); - if (!pluginsPath.empty() && (pluginsPath != "None")) + if (!pluginsPath.empty() && (pluginsPath != _("None"))) ConfMan.set("pluginspath", pluginsPath, _domain); else ConfMan.removeKey("pluginspath", _domain); @@ -940,6 +1070,28 @@ void GlobalOptionsDialog::close() { g_gui.loadNewTheme(g_gui.theme()->getThemeId(), selected); ConfMan.set("gui_renderer", cfg, _domain); } +#ifdef USE_TRANSLATION + Common::String oldLang = ConfMan.get("gui_language"); + int selLang = _guiLanguagePopUp->getSelectedTag(); + + ConfMan.set("gui_language", TransMan.getLangById(selLang)); + + Common::String newLang = ConfMan.get("gui_language").c_str(); + if (newLang != oldLang) { +#if 0 + // Activate the selected language + TransMan.setLanguage(selLang); + + // FIXME: Actually, any changes (including the theme change) should + // only become active *after* the options dialog has closed. + g_gui.loadNewTheme(g_gui.theme()->getThemeId(), ThemeEngine::kGfxDisabled, true); +#else + MessageDialog error(_("You have to restart ScummVM to take the effect.")); + error.runModal(); +#endif + } +#endif // USE_TRANSLATION + } OptionsDialog::close(); } @@ -947,14 +1099,14 @@ void GlobalOptionsDialog::close() { void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { switch (cmd) { case kChooseSaveDirCmd: { - BrowserDialog browser("Select directory for savegames", true); + BrowserDialog browser(_("Select directory for savegames"), true); if (browser.runModal() > 0) { // User made his choice... Common::FSNode dir(browser.getResult()); if (dir.isWritable()) { _savePath->setLabel(dir.getPath()); } else { - MessageDialog error("The chosen directory cannot be written to. Please select another one."); + MessageDialog error(_("The chosen directory cannot be written to. Please select another one.")); error.runModal(); return; } @@ -963,7 +1115,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 break; } case kChooseThemeDirCmd: { - BrowserDialog browser("Select directory for GUI themes", true); + BrowserDialog browser(_("Select directory for GUI themes"), true); if (browser.runModal() > 0) { // User made his choice... Common::FSNode dir(browser.getResult()); @@ -973,7 +1125,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 break; } case kChooseExtraDirCmd: { - BrowserDialog browser("Select directory for extra files", true); + BrowserDialog browser(_("Select directory for extra files"), true); if (browser.runModal() > 0) { // User made his choice... Common::FSNode dir(browser.getResult()); @@ -984,7 +1136,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 } #ifdef DYNAMIC_MODULES case kChoosePluginsDirCmd: { - BrowserDialog browser("Select directory for plugins", true); + BrowserDialog browser(_("Select directory for plugins"), true); if (browser.runModal() > 0) { // User made his choice... Common::FSNode dir(browser.getResult()); @@ -995,13 +1147,13 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3 } #endif case kChooseSoundFontCmd: { - BrowserDialog browser("Select SoundFont", false); + BrowserDialog browser(_("Select SoundFont"), false); if (browser.runModal() > 0) { // User made his choice... Common::FSNode file(browser.getResult()); _soundFont->setLabel(file.getPath()); - if (!file.getPath().empty() && (file.getPath() != "None")) + if (!file.getPath().empty() && (file.getPath() != _("None"))) _soundFontClearButton->setEnabled(true); else _soundFontClearButton->setEnabled(false); diff --git a/gui/options.h b/gui/options.h index 956f78c18f..235cb24462 100644 --- a/gui/options.h +++ b/gui/options.h @@ -28,6 +28,7 @@ #include "gui/dialog.h" #include "gui/TabWidget.h" #include "common/str.h" +#include "sound/musicplugin.h" #ifdef SMALL_SCREEN_DEVICE #include "gui/KeysDialog.h" @@ -78,6 +79,9 @@ protected: void setVolumeSettingsState(bool enabled); void setSubtitleSettingsState(bool enabled); + bool loadMusicDeviceSetting(PopUpWidget *popup, Common::String setting, MusicType preferredType = MT_AUTO); + void saveMusicDeviceSetting(PopUpWidget *popup, Common::String setting); + TabWidget *_tabWidget; int _graphicsTabId; @@ -104,6 +108,13 @@ private: StaticTextWidget *_outputRatePopUpDesc; PopUpWidget *_outputRatePopUp; + StaticTextWidget *_mt32DevicePopUpDesc; + PopUpWidget *_mt32DevicePopUp; + StaticTextWidget *_gmDevicePopUpDesc; + PopUpWidget *_gmDevicePopUp; + + + // // MIDI controls // @@ -121,8 +132,10 @@ private: int getSubtitleMode(bool subtitles, bool speech_mute); bool _enableSubtitleSettings; StaticTextWidget *_subToggleDesc; - ButtonWidget *_subToggleButton; - int _subMode; + RadiobuttonGroup *_subToggleGroup; + RadiobuttonWidget *_subToggleSubOnly; + RadiobuttonWidget *_subToggleSpeechOnly; + RadiobuttonWidget *_subToggleSubBoth; static const char *_subModeDesc[]; static const char *_lowresSubModeDesc[]; StaticTextWidget *_subSpeedDesc; @@ -153,6 +166,7 @@ protected: // Game GUI options // uint32 _guioptions; + Common::String _guioptionsString; }; @@ -184,6 +198,8 @@ protected: PopUpWidget *_rendererPopUp; StaticTextWidget *_autosavePeriodPopUpDesc; PopUpWidget *_autosavePeriodPopUp; + StaticTextWidget *_guiLanguagePopUpDesc; + PopUpWidget *_guiLanguagePopUp; }; } // End of namespace GUI diff --git a/gui/saveload.cpp b/gui/saveload.cpp index 8ec4dc4133..92cea00f30 100644 --- a/gui/saveload.cpp +++ b/gui/saveload.cpp @@ -23,6 +23,7 @@ */ #include "common/config-manager.h" +#include "common/translation.h" #include "gui/ListWidget.h" #include "gui/message.h" @@ -56,16 +57,16 @@ SaveLoadChooser::SaveLoadChooser(const String &title, const String &buttonLabel) _gfxWidget = new GUI::GraphicsWidget(this, 0, 0, 10, 10); - _date = new StaticTextWidget(this, 0, 0, 10, 10, "No date saved", Graphics::kTextAlignCenter); - _time = new StaticTextWidget(this, 0, 0, 10, 10, "No time saved", Graphics::kTextAlignCenter); - _playtime = new StaticTextWidget(this, 0, 0, 10, 10, "No playtime saved", Graphics::kTextAlignCenter); + _date = new StaticTextWidget(this, 0, 0, 10, 10, _("No date saved"), Graphics::kTextAlignCenter); + _time = new StaticTextWidget(this, 0, 0, 10, 10, _("No time saved"), Graphics::kTextAlignCenter); + _playtime = new StaticTextWidget(this, 0, 0, 10, 10, _("No playtime saved"), Graphics::kTextAlignCenter); // Buttons - new GUI::ButtonWidget(this, "SaveLoadChooser.Cancel", "Cancel", kCloseCmd, 0); - _chooseButton = new GUI::ButtonWidget(this, "SaveLoadChooser.Choose", buttonLabel, kChooseCmd, 0); + new GUI::ButtonWidget(this, "SaveLoadChooser.Cancel", _("Cancel"), 0, kCloseCmd); + _chooseButton = new GUI::ButtonWidget(this, "SaveLoadChooser.Choose", buttonLabel, 0, kChooseCmd); _chooseButton->setEnabled(false); - _deleteButton = new GUI::ButtonWidget(this, "SaveLoadChooser.Delete", "Delete", kDelCmd, 0); + _deleteButton = new GUI::ButtonWidget(this, "SaveLoadChooser.Delete", _("Delete"), 0, kDelCmd); _deleteButton->setEnabled(false); _delSupport = _metaInfoSupport = _thumbnailSupport = false; @@ -152,8 +153,8 @@ void SaveLoadChooser::handleCommand(CommandSender *sender, uint32 cmd, uint32 da break; case kDelCmd: if (selItem >= 0 && _delSupport) { - MessageDialog alert("Do you really want to delete this savegame?", - "Delete", "Cancel"); + MessageDialog alert(_("Do you really want to delete this savegame?"), + _("Delete"), _("Cancel")); if (alert.runModal() == GUI::kMessageOK) { (*_plugin)->removeSaveState(_target.c_str(), atoi(_saveList[selItem].save_slot().c_str())); @@ -181,7 +182,7 @@ void SaveLoadChooser::reflowLayout() { error("Error when loading position data for Save/Load Thumbnails."); int thumbW = kThumbnailWidth; - int thumbH = ((g_system->getHeight() % 200 && g_system->getHeight() != 350) ? kThumbnailHeight2 : kThumbnailHeight1); + int thumbH = kThumbnailHeight2; int thumbX = x + (w >> 1) - (thumbW >> 1); int thumbY = y + kLineHeight; @@ -237,9 +238,9 @@ void SaveLoadChooser::updateSelection(bool redraw) { bool startEditMode = _list->isEditable(); _gfxWidget->setGfx(-1, -1, _fillR, _fillG, _fillB); - _date->setLabel("No date saved"); - _time->setLabel("No time saved"); - _playtime->setLabel("No playtime saved"); + _date->setLabel(_("No date saved")); + _time->setLabel(_("No time saved")); + _playtime->setLabel(_("No playtime saved")); if (selItem >= 0 && !_list->getSelectedString().empty() && _metaInfoSupport) { SaveStateDescriptor desc = (*_plugin)->querySaveMetaInfos(_target.c_str(), atoi(_saveList[selItem].save_slot().c_str())); @@ -261,15 +262,15 @@ void SaveLoadChooser::updateSelection(bool redraw) { if (_saveDateSupport) { if (desc.contains("save_date")) - _date->setLabel("Date: " + desc.getVal("save_date")); + _date->setLabel(_("Date: ") + desc.getVal("save_date")); if (desc.contains("save_time")) - _time->setLabel("Time: " + desc.getVal("save_time")); + _time->setLabel(_("Time: ") + desc.getVal("save_time")); } if (_playTimeSupport) { if (desc.contains("play_time")) - _playtime->setLabel("Playtime: " + desc.getVal("play_time")); + _playtime->setLabel(_("Playtime: ") + desc.getVal("play_time")); } } @@ -282,7 +283,7 @@ void SaveLoadChooser::updateSelection(bool redraw) { if (startEditMode) { _list->startEditMode(); - if (_chooseButton->isEnabled() && _list->getSelectedString() == "Untitled savestate" && + if (_chooseButton->isEnabled() && _list->getSelectedString() == _("Untitled savestate") && _list->getSelectionColor() == ThemeEngine::kFontColorAlternate) { _list->setEditString(""); _list->setEditColor(ThemeEngine::kFontColorNormal); @@ -349,7 +350,7 @@ void SaveLoadChooser::updateSaveList() { Common::String trimmedDescription = description; trimmedDescription.trim(); if (trimmedDescription.empty()) { - description = "Untitled savestate"; + description = _("Untitled savestate"); colors.push_back(ThemeEngine::kFontColorAlternate); } else { colors.push_back(ThemeEngine::kFontColorNormal); diff --git a/gui/themebrowser.cpp b/gui/themebrowser.cpp index 5d0e24394f..c8f732fe5f 100644 --- a/gui/themebrowser.cpp +++ b/gui/themebrowser.cpp @@ -26,6 +26,8 @@ #include "gui/ListWidget.h" #include "gui/widget.h" +#include "common/translation.h" + namespace GUI { enum { @@ -41,7 +43,7 @@ enum { ThemeBrowser::ThemeBrowser() : Dialog("Browser") { _fileList = 0; - new StaticTextWidget(this, "Browser.Headline", "Select a Theme"); + new StaticTextWidget(this, "Browser.Headline", _("Select a Theme")); // Add file list _fileList = new ListWidget(this, "Browser.List"); @@ -51,8 +53,8 @@ ThemeBrowser::ThemeBrowser() : Dialog("Browser") { _backgroundType = GUI::ThemeEngine::kDialogBackgroundPlain; // Buttons - new ButtonWidget(this, "Browser.Cancel", "Cancel", kCloseCmd, 0); - new ButtonWidget(this, "Browser.Choose", "Choose", kChooseCmd, 0); + new ButtonWidget(this, "Browser.Cancel", _("Cancel"), 0, kCloseCmd); + new ButtonWidget(this, "Browser.Choose", _("Choose"), 0, kChooseCmd); } void ThemeBrowser::open() { diff --git a/gui/themes/default.inc b/gui/themes/default.inc index 93897a7d88..086fecc123 100644 --- a/gui/themes/default.inc +++ b/gui/themes/default.inc @@ -1,397 +1,44 @@ "<?xml version = '1.0'?>" -"<render_info> " -"<palette> " -"<color name='black' " -"rgb='0,0,0' " -"/> " -"<color name='lightgrey' " -"rgb='104,104,104' " -"/> " -"<color name='darkgrey' " -"rgb='64,64,64' " -"/> " -"<color name='green' " -"rgb='32,160,32' " -"/> " -"<color name='green2' " -"rgb='0,255,0' " -"/> " -"</palette> " -"<fonts> " -"<font id='text_default' " -"file='default' " -"/> " -"<font id='text_button' " -"file='default' " -"/> " -"<font id='text_normal' " -"file='default' " -"/> " -"<text_color id='color_normal' " -"color='green' " -"/> " -"<text_color id='color_normal_inverted' " -"color='black' " -"/> " -"<text_color id='color_normal_hover' " -"color='green2' " -"/> " -"<text_color id='color_normal_disabled' " -"color='lightgrey' " -"/> " -"<text_color id='color_alternative' " -"color='lightgrey' " -"/> " -"<text_color id='color_alternative_inverted' " -"color='255,255,255' " -"/> " -"<text_color id='color_alternative_hover' " -"color='176,176,176' " -"/> " -"<text_color id='color_alternative_disabled' " -"color='darkgrey' " -"/> " -"<text_color id='color_button' " -"color='green' " -"/> " -"<text_color id='color_button_hover' " -"color='green2' " -"/> " -"<text_color id='color_button_disabled' " -"color='lightgrey' " -"/> " -"</fonts> " -"<defaults fill='foreground' fg_color='darkgrey' bg_color='black' shadow='0' bevel_color='lightgrey'/> " -"<drawdata id='text_selection' cache='false'> " -"<drawstep func='square' " -"fill='foreground' " -"fg_color='lightgrey' " -"/> " -"</drawdata> " -"<drawdata id='text_selection_focus' cache='false'> " -"<drawstep func='square' " -"fill='foreground' " -"fg_color='green' " -"/> " -"</drawdata> " -"<drawdata id='mainmenu_bg' cache='false'> " -"<drawstep func='fill' " -"fill='foreground' " -"fg_color='black' " -"/> " -"</drawdata> " -"<drawdata id='special_bg' cache='false'> " -"<drawstep func='bevelsq' " -"bevel='2' " -"/> " -"</drawdata> " -"<drawdata id='separator' cache='false'> " -"<drawstep func='square' " -"fill='foreground' " -"height='2' " -"ypos='center' " -"fg_color='lightgrey' " -"/> " -"</drawdata> " -"<drawdata id='scrollbar_base' cache='false'> " -"<drawstep func='bevelsq' " -"bevel='2' " -"/> " -"</drawdata> " -"<drawdata id='scrollbar_handle_hover' cache='false'> " -"<drawstep func='square' " -"fill='foreground' " -"fg_color='green2' " -"/> " -"</drawdata> " -"<drawdata id='scrollbar_handle_idle' cache='false'> " -"<drawstep func='square' " -"fill='foreground' " -"fg_color='green' " -"/> " -"</drawdata> " -"<drawdata id='scrollbar_button_idle' cache='false'> " -"<drawstep func='bevelsq' " -"bevel='2' " -"fill='none' " -"/> " -"<drawstep func='triangle' " -"fg_color='green' " -"fill='foreground' " -"width='auto' " -"height='auto' " -"xpos='center' " -"ypos='center' " -"orientation='top' " -"/> " -"</drawdata> " -"<drawdata id='scrollbar_button_hover' cache='false'> " -"<drawstep func='bevelsq' " -"bevel='2' " -"fill='none' " -"/> " -"<drawstep func='triangle' " -"fg_color='green2' " -"fill='foreground' " -"width='auto' " -"height='auto' " -"xpos='center' " -"ypos='center' " -"orientation='top' " -"/> " -"</drawdata> " -"<drawdata id='tab_active' cache='false'> " -"<text font='text_default' " -"text_color='color_normal_hover' " -"vertical_align='center' " -"horizontal_align='center' " -"/> " -"<drawstep func='tab' " -"bevel='2' " -"radius='0' " -"fill='none' " -"/> " -"</drawdata> " -"<drawdata id='tab_inactive' cache='false'> " -"<text font='text_default' " -"text_color='color_normal' " -"vertical_align='center' " -"horizontal_align='center' " -"/> " -"<drawstep func='tab' " -"bevel='2' " -"radius='0' " -"fill='none' " -"/> " -"</drawdata> " -"<drawdata id='tab_background' cache='false'> " -"</drawdata> " -"<drawdata id='widget_slider' cache='false'> " -"<drawstep func='bevelsq' " -"bevel='2' " -"fill='none' " -"/> " -"</drawdata> " -"<drawdata id='slider_disabled' cache='false'> " -"<drawstep func='square' " -"fill='foreground' " -"fg_color='lightgrey' " -"/> " -"</drawdata> " -"<drawdata id='slider_full' cache='false'> " -"<drawstep func='square' " -"fill='foreground' " -"fg_color='green' " -"/> " -"</drawdata> " -"<drawdata id='slider_hover' cache='false'> " -"<drawstep func='square' " -"fill='foreground' " -"fg_color='green2' " -"/> " -"</drawdata> " -"<drawdata id='widget_small' cache='false'> " -"<drawstep func='bevelsq' " -"bevel='2' " -"fill='none' " -"/> " -"</drawdata> " -"<drawdata id='popup_idle' cache='false'> " -"<drawstep func='bevelsq' " -"bevel='2' " -"fill='none' " -"/> " -"<drawstep func='triangle' " -"fg_color='green' " -"fill='foreground' " -"width='height' " -"height='auto' " -"xpos='right' " -"ypos='center' " -"orientation='bottom' " -"/> " -"<text font='text_default' " -"text_color='color_normal' " -"vertical_align='center' " -"horizontal_align='left' " -"/> " -"</drawdata> " -"<drawdata id='popup_disabled' cache='false'> " -"<drawstep func='bevelsq' " -"bevel='2' " -"fill='none' " -"/> " -"<drawstep func='triangle' " -"fg_color='lightgrey' " -"fill='foreground' " -"width='height' " -"height='auto' " -"xpos='right' " -"ypos='center' " -"orientation='bottom' " -"/> " -"<text font='text_default' " -"text_color='color_normal_disabled' " -"vertical_align='center' " -"horizontal_align='left' " -"/> " -"</drawdata> " -"<drawdata id='popup_hover' cache='false'> " -"<drawstep func='bevelsq' " -"bevel='2' " -"fill='none' " -"/> " -"<drawstep func='triangle' " -"fg_color='green2' " -"fill='foreground' " -"width='height' " -"height='auto' " -"xpos='right' " -"ypos='center' " -"orientation='bottom' " -"/> " -"<text font='text_default' " -"text_color='color_normal_hover' " -"vertical_align='center' " -"horizontal_align='left' " -"/> " -"</drawdata> " -"<drawdata id='widget_textedit' cache='false'> " -"<drawstep func='bevelsq' " -"bevel='2' " -"fill='none' " -"/> " -"</drawdata> " -"<drawdata id='plain_bg' cache='false'> " -"<drawstep func='bevelsq' " -"bevel='2' " -"/> " -"</drawdata> " -"<drawdata id='caret' cache='false'> " -"<drawstep func='square' " -"fill='foreground' " -"fg_color='lightgrey' " -"/> " -"</drawdata> " -"<drawdata id='default_bg' cache='false'> " -"<drawstep func='bevelsq' " -"bevel='2' " -"/> " -"</drawdata> " -"<drawdata id='button_idle' cache='false'> " -"<text font='text_button' " -"text_color='color_button' " -"vertical_align='center' " -"horizontal_align='center' " -"/> " -"<drawstep func='bevelsq' " -"bevel='2' " -"fill='none' " -"/> " -"</drawdata> " -"<drawdata id='button_hover' cache='false'> " -"<text font='text_button' " -"text_color='color_button_hover' " -"vertical_align='center' " -"horizontal_align='center' " -"/> " -"<drawstep func='bevelsq' " -"bevel='2' " -"fill='none' " -"/> " -"</drawdata> " -"<drawdata id='button_disabled' cache='false'> " -"<text font='text_button' " -"text_color='color_button_disabled' " -"vertical_align='center' " -"horizontal_align='center' " -"/> " -"<drawstep func='bevelsq' " -"bevel='2' " -"fill='none' " -"/> " -"</drawdata> " -"<drawdata id='checkbox_disabled' cache='false'> " -"<text font='text_default' " -"text_color='color_normal_disabled' " -"vertical_align='top' " -"horizontal_align='left' " -"/> " -"<drawstep func='bevelsq' " -"bevel='2' " -"fill='none' " -"/> " -"</drawdata> " -"<drawdata id='checkbox_selected' cache='false'> " -"<text font='text_default' " -"text_color='color_normal' " -"vertical_align='top' " -"horizontal_align='left' " -"/> " -"<drawstep func='bevelsq' " -"bevel='2' " -"fill='none' " -"/> " -"<drawstep func='cross' " -"fill='foreground' " -"stroke='2' " -"fg_color='green' " -"/> " -"</drawdata> " -"<drawdata id='checkbox_default' cache='false'> " -"<text font='text_default' " -"text_color='color_normal' " -"vertical_align='top' " -"horizontal_align='left' " -"/> " -"<drawstep func='bevelsq' " -"bevel='2' " -"fill='none' " -"/> " -"</drawdata> " -"<drawdata id='widget_default' cache='false'> " -"<drawstep func='bevelsq' " -"bevel='2' " -"/> " -"</drawdata> " -"</render_info> " -"<layout_info resolution='-320xY,-256x240,-Xx272'> " +"<layout_info resolution='320xY,256x240,Xx272'> " "<globals> " -"<def var='Line.Height' value='16' /> " -"<def var='Font.Height' value='16' /> " -"<def var='About.OuterBorder' value='80'/> " -"<def var='Layout.Spacing' value='8' /> " +"<def var='Line.Height' value='12' /> " +"<def var='Font.Height' value='10' /> " +"<def var='About.OuterBorder' value='10'/> " +"<def var='Layout.Spacing' value='8'/> " "<def var='ShowLauncherLogo' value='0'/> " "<def var='ShowGlobalMenuLogo' value='0'/> " "<def var='ShowSearchPic' value='0'/> " -"<def var='SaveLoadChooser.ExtInfo.Visible' value='1'/> " -"<def var='KeyMapper.Spacing' value='10'/> " -"<def var='KeyMapper.LabelWidth' value='100'/> " -"<def var='KeyMapper.ButtonWidth' value='80'/> " +"<def var='SaveLoadChooser.ExtInfo.Visible' value='0'/> " +"<def var='KeyMapper.Spacing' value='5'/> " +"<def var='KeyMapper.LabelWidth' value='80'/> " +"<def var='KeyMapper.ButtonWidth' value='60'/> " +"<def var='Tooltip.MaxWidth' value='70'/> " +"<def var='Tooltip.XDelta' value='8'/> " +"<def var='Tooltip.YDelta' value='8'/> " +"<widget name='Button' " +"size='72,16' " +"/> " +"<widget name='Slider' " +"size='85,12' " +"/> " "<widget name='OptionsLabel' " "size='110,Globals.Line.Height' " "textalign='right' " "/> " "<widget name='SmallLabel' " -"size='24,Globals.Line.Height' " -"/> " -"<widget name='ShortOptionsLabel' " -"size='60,Globals.Line.Height' " -"/> " -"<widget name='Button' " -"size='108,24' " -"/> " -"<widget name='Slider' " -"size='128,18' " +"size='18,Globals.Line.Height' " "/> " "<widget name='PopUp' " -"size='-1,19' " +"size='-1,15' " "/> " "<widget name='Checkbox' " -"size='-1,14' " +"size='-1,Globals.Line.Height' " +"/> " +"<widget name='Radiobutton' " +"size='-1,Globals.Line.Height' " "/> " "<widget name='ListWidget' " -"padding='5,0,8,0' " +"padding='5,0,0,0' " "/> " "<widget name='PopUpWidget' " "padding='7,5,0,0' " @@ -403,25 +50,28 @@ "padding='7,5,5,5' " "/> " "<widget name='Scrollbar' " -"size='15,0' " +"size='9,0' " "/> " "<widget name='TabWidget.Tab' " -"size='75,27' " -"padding='0,0,8,0' " +"size='45,16' " +"padding='0,0,2,0' " +"/> " +"<widget name='TabWidget.Body' " +"padding='0,0,0,0' " "/> " "<widget name='TabWidget.NavButton' " -"size='15,18' " +"size='32,18' " "padding='0,3,4,0' " "/> " "</globals> " "<dialog name='Launcher' overlays='screen'> " -"<layout type='vertical' center='true' padding='16,16,8,8'> " +"<layout type='vertical' center='true' padding='6,6,2,2'> " "<widget name='Version' " "height='Globals.Line.Height' " "/> " -"<layout type='horizontal' spacing='5' padding='10,0,0,0'> " +"<layout type='horizontal' spacing='5' padding='0,0,0,0'> " "<widget name='SearchDesc' " -"width='60' " +"width='50' " "height='Globals.Line.Height' " "textalign='right' " "/> " @@ -436,39 +86,38 @@ "<space /> " "</layout> " "<widget name='GameList'/> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='8'> " "<widget name='LoadGameButton' " -"height='20' " +"height='12' " "/> " "<widget name='AddGameButton' " -"height='20' " +"height='12' " "/> " "<widget name='EditGameButton' " -"height='20' " +"height='12' " "/> " "<widget name='RemoveGameButton' " -"height='20' " +"height='12' " "/> " "</layout> " -"<space size='4'/> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='8'> " "<widget name='QuitButton' " -"height='20' " +"height='12' " "/> " "<widget name='AboutButton' " -"height='20' " +"height='12' " "/> " "<widget name='OptionsButton' " -"height='20' " +"height='12' " "/> " "<widget name='StartButton' " -"height='20' " +"height='12' " "/> " "</layout> " "</layout> " "</dialog> " -"<dialog name='Browser' overlays='Dialog.Launcher.GameList' shading='dim'> " -"<layout type='vertical' padding='8,8,8,8'> " +"<dialog name='Browser' overlays='screen' inset='8' shading='dim'> " +"<layout type='vertical' padding='8,8,0,4'> " "<widget name='Headline' " "height='Globals.Line.Height' " "/> " @@ -476,7 +125,7 @@ "height='Globals.Line.Height' " "/> " "<widget name='List'/> " -"<layout type='horizontal' padding='0,0,16,0'> " +"<layout type='horizontal' padding='0,0,8,0'> " "<widget name='Up' " "type='Button' " "/> " @@ -490,10 +139,10 @@ "</layout> " "</layout> " "</dialog> " -"<dialog name='GlobalOptions' overlays='Dialog.Launcher.GameList' shading='dim'> " +"<dialog name='GlobalOptions' overlays='screen' inset='16' shading='dim'> " "<layout type='vertical' padding='0,0,0,0'> " "<widget name='TabWidget'/> " -"<layout type='horizontal' padding='16,16,16,16'> " +"<layout type='horizontal' padding='8,8,8,8'> " "<space/> " "<widget name='Cancel' " "type='Button' " @@ -506,7 +155,7 @@ "</dialog> " "<dialog name='GlobalOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> " "<layout type='vertical' padding='16,16,16,16' spacing='8'> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='grModePopupDesc' " "type='OptionsLabel' " "/> " @@ -514,7 +163,7 @@ "type='PopUp' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='grRenderPopupDesc' " "type='OptionsLabel' " "/> " @@ -532,7 +181,7 @@ "</dialog> " "<dialog name='GlobalOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> " "<layout type='vertical' padding='16,16,16,16' spacing='8'> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='auMidiPopupDesc' " "type='OptionsLabel' " "/> " @@ -540,7 +189,23 @@ "type='PopUp' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<widget name='auPrefMt32PopupDesc' " +"type='OptionsLabel' " +"/> " +"<widget name='auPrefMt32Popup' " +"type='PopUp' " +"/> " +"</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<widget name='auPrefGmPopupDesc' " +"type='OptionsLabel' " +"/> " +"<widget name='auPrefGmPopup' " +"type='PopUp' " +"/> " +"</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='auOPLPopupDesc' " "type='OptionsLabel' " "/> " @@ -548,7 +213,7 @@ "type='PopUp' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='auSampleRatePopupDesc' " "type='OptionsLabel' " "/> " @@ -556,16 +221,21 @@ "type='PopUp' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='3' center='true'> " "<widget name='subToggleDesc' " "type='OptionsLabel' " "/> " -"<widget name='subToggleButton' " -"width='150' " -"height='Globals.Slider.Height' " +"<widget name='subToggleSpeechOnly' " +"type='Radiobutton' " +"/> " +"<widget name='subToggleSubOnly' " +"type='Radiobutton' " +"/> " +"<widget name='subToggleSubBoth' " +"type='Radiobutton' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='subSubtitleSpeedDesc' " "type='OptionsLabel' " "/> " @@ -579,9 +249,8 @@ "</layout> " "</dialog> " "<dialog name='GlobalOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> " -"<layout type='horizontal' padding='16,16,16,16' spacing='8'> " -"<layout type='vertical' padding='0,0,0,0' spacing='8'> " -"<layout type='horizontal' padding='0,0,0,0'> " +"<layout type='vertical' padding='16,16,16,16' spacing='8'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='vcMusicText' " "type='OptionsLabel' " "/> " @@ -592,7 +261,7 @@ "type='SmallLabel' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='vcSfxText' " "type='OptionsLabel' " "/> " @@ -603,7 +272,7 @@ "type='SmallLabel' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='vcSpeechText' " "type='OptionsLabel' " "/> " @@ -614,8 +283,8 @@ "type='SmallLabel' " "/> " "</layout> " -"</layout> " -"<layout type='vertical' padding='24,0,24,0' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<space size='110' /> " "<widget name='vcMuteCheckbox' " "type='Checkbox' " "/> " @@ -624,7 +293,7 @@ "</dialog> " "<dialog name='GlobalOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> " "<layout type='vertical' padding='16,16,16,16' spacing='8'> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> " "<widget name='mcFontButton' " "type='Button' " "/> " @@ -645,7 +314,7 @@ "<widget name='mcGSCheckbox' " "type='Checkbox' " "/> " -"<layout type='horizontal' padding='0,0,0,0'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='mcMidiGainText' " "type='OptionsLabel' " "/> " @@ -661,7 +330,7 @@ "</dialog> " "<dialog name='GlobalOptions_Paths' overlays='Dialog.GlobalOptions.TabWidget'> " "<layout type='vertical' padding='16,16,16,16' spacing='8'> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='16'> " "<widget name='SaveButton' " "type='Button' " "/> " @@ -669,7 +338,7 @@ "height='Globals.Line.Height' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='16'> " "<widget name='ThemeButton' " "type='Button' " "/> " @@ -677,7 +346,7 @@ "height='Globals.Line.Height' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='16'> " "<widget name='ExtraButton' " "type='Button' " "/> " @@ -697,7 +366,7 @@ "</dialog> " "<dialog name='GlobalOptions_Misc' overlays='Dialog.GlobalOptions.TabWidget'> " "<layout type='vertical' padding='16,16,16,16' spacing='8'> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='16'> " "<widget name='ThemeButton' " "type='Button' " "/> " @@ -705,22 +374,36 @@ "height='Globals.Line.Height' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='RendererPopupDesc' " -"type='OptionsLabel' " +"width='80' " +"height='Globals.Line.Height' " +"textalign='right' " "/> " "<widget name='RendererPopup' " "type='PopUp' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='AutosavePeriodPopupDesc' " -"type='OptionsLabel' " +"width='80' " +"height='Globals.Line.Height' " +"textalign='right' " "/> " "<widget name='AutosavePeriodPopup' " "type='PopUp' " "/> " "</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<widget name='GuiLanguagePopupDesc' " +"width='80' " +"height='Globals.Line.Height' " +"textalign='right' " +"/> " +"<widget name='GuiLanguagePopup' " +"type='PopUp' " +"/> " +"</layout> " "<widget name='KeysButton' " "type='Button' " "/> " @@ -750,10 +433,10 @@ "</layout> " "</layout> " "</dialog> " -"<dialog name='GameOptions' overlays='Dialog.Launcher.GameList' shading='dim'> " +"<dialog name='GameOptions' overlays='screen' inset='16' shading='dim'> " "<layout type='vertical' padding='0,0,0,0' spacing='16'> " "<widget name='TabWidget'/> " -"<layout type='horizontal' padding='16,16,16,4'> " +"<layout type='horizontal' padding='8,8,8,8'> " "<space/> " "<widget name='Cancel' " "type='Button' " @@ -765,7 +448,7 @@ "</layout> " "</dialog> " "<dialog name='GameOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> " -"<layout type='vertical' padding='16,16,16,16' spacing='8'> " +"<layout type='vertical' padding='8,8,8,8' spacing='6'> " "<widget name='EnableTabCheckbox' " "type='Checkbox' " "/> " @@ -773,7 +456,7 @@ "</layout> " "</dialog> " "<dialog name='GameOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> " -"<layout type='vertical' padding='16,16,16,16' spacing='8'> " +"<layout type='vertical' padding='8,8,8,8' spacing='6'> " "<widget name='EnableTabCheckbox' " "type='Checkbox' " "/> " @@ -781,7 +464,7 @@ "</layout> " "</dialog> " "<dialog name='GameOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> " -"<layout type='vertical' padding='16,16,16,16' spacing='8'> " +"<layout type='vertical' padding='8,8,8,8' spacing='6'> " "<widget name='EnableTabCheckbox' " "type='Checkbox' " "/> " @@ -789,7 +472,7 @@ "</layout> " "</dialog> " "<dialog name='GameOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> " -"<layout type='vertical' padding='16,16,16,16' spacing='8'> " +"<layout type='vertical' padding='8,8,8,8' spacing='6'> " "<widget name='EnableTabCheckbox' " "type='Checkbox' " "/> " @@ -797,34 +480,43 @@ "</layout> " "</dialog> " "<dialog name='GameOptions_Game' overlays='Dialog.GameOptions.TabWidget' shading='dim'> " -"<layout type='vertical' padding='16,16,16,16'> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<layout type='vertical' padding='8,8,8,8'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='Id' " -"type='OptionsLabel' " +"width='35' " +"height='Globals.Line.Height' " +"textalign='right' " "/> " "<widget name='Domain' " "type='PopUp' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='Name' " -"type='OptionsLabel' " +"width='35' " +"height='Globals.Line.Height' " +"textalign='right' " "/> " "<widget name='Desc' " "type='PopUp' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<space size='8'/> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='LangPopupDesc' " -"type='OptionsLabel' " +"width='60' " +"height='Globals.Line.Height' " +"textalign='right' " "/> " "<widget name='LangPopup' " "type='PopUp' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='PlatformPopupDesc' " -"type='OptionsLabel' " +"width='60' " +"height='Globals.Line.Height' " +"textalign='right' " "/> " "<widget name='PlatformPopup' " "type='PopUp' " @@ -833,8 +525,8 @@ "</layout> " "</dialog> " "<dialog name='GameOptions_Paths' overlays='Dialog.GameOptions.TabWidget' shading='dim'> " -"<layout type='vertical' padding='16,16,16,16'> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<layout type='vertical' padding='8,8,8,8'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> " "<widget name='Savepath' " "type='Button' " "/> " @@ -842,7 +534,7 @@ "height='Globals.Line.Height' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> " "<widget name='Extrapath' " "type='Button' " "/> " @@ -850,7 +542,7 @@ "height='Globals.Line.Height' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> " "<widget name='Gamepath' " "type='Button' " "/> " @@ -861,57 +553,55 @@ "</layout> " "</dialog> " "<dialog name='GlobalMenu' overlays='screen_center'> " -"<layout type='vertical' padding='16,16,16,16' center='true'> " +"<layout type='vertical' padding='2,2,4,6' center='true' spacing='6'> " "<widget name='Title' " -"width='210' " -"height='Globals.Line.Height' " +"width='160' " +"height='4' " "/> " "<widget name='Version' " -"width='210' " -"height='Globals.Line.Height' " -"/> " -"<widget name='Resume' " -"width='150' " -"height='Globals.Button.Height' " +"width='160' " +"height='4' " "/> " -"<space size='10'/> " +"<space size='1'/> " "<widget name='Load' " -"width='150' " -"height='Globals.Button.Height' " +"width='120' " +"height='12' " "/> " "<widget name='Save' " -"width='150' " -"height='Globals.Button.Height' " +"width='120' " +"height='12' " "/> " -"<space size='10'/> " +"<space size='1'/> " "<widget name='Options' " -"width='150' " -"height='Globals.Button.Height' " +"width='120' " +"height='12' " "/> " "<widget name='Help' " -"width='150' " -"height='Globals.Button.Height' " +"width='120' " +"height='12' " "/> " "<widget name='About' " -"width='150' " -"height='Globals.Button.Height' " +"width='120' " +"height='12' " +"/> " +"<space size='1'/> " +"<widget name='Resume' " +"width='120' " +"height='12' " "/> " -"<space size='10'/> " "<widget name='RTL' " -"width='150' " -"height='Globals.Button.Height' " +"width='120' " +"height='12' " "/> " "<widget name='Quit' " -"width='150' " -"height='Globals.Button.Height' " +"width='120' " +"height='12' " "/> " "</layout> " "</dialog> " "<dialog name='GlobalConfig' overlays='screen_center'> " "<layout type='vertical' padding='8,8,8,8'> " -"<layout type='horizontal' padding='0,0,0,0'> " -"<layout type='vertical' padding='0,0,0,0' center='true'> " -"<layout type='horizontal' padding='0,0,0,0' spacing='8'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='vcMusicText' " "type='OptionsLabel' " "/> " @@ -922,7 +612,7 @@ "type='SmallLabel' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='8'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='vcSfxText' " "type='OptionsLabel' " "/> " @@ -933,7 +623,7 @@ "type='SmallLabel' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='8'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='vcSpeechText' " "type='OptionsLabel' " "/> " @@ -944,25 +634,35 @@ "type='SmallLabel' " "/> " "</layout> " -"</layout> " -"<layout type='vertical' padding='24,24,24,24' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<space size='110' /> " "<widget name='vcMuteCheckbox' " "type='Checkbox' " -"width='80' " +"width='80' " "/> " "</layout> " -"</layout> " -"<space size='8' /> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10'> " +"<space size='4' /> " +"<layout type='vertical' padding='0,0,0,0' spacing='1' center='true'> " "<widget name='subToggleDesc' " "type='OptionsLabel' " "/> " -"<widget name='subToggleButton' " -"width='158' " -"height='Globals.Slider.Height' " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<widget name='subToggleSpeechOnly' " +"type='Radiobutton' " +"width='90' " +"/> " +"<widget name='subToggleSubOnly' " +"type='Radiobutton' " +"width='90' " +"/> " +"<widget name='subToggleSubBoth' " +"type='Radiobutton' " +"width='90' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10'> " +"</layout> " +"<space size='4' /> " +"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " "<widget name='subSubtitleSpeedDesc' " "type='OptionsLabel' " "/> " @@ -973,8 +673,8 @@ "type='SmallLabel' " "/> " "</layout> " -"<space size='60'/> " -"<layout type='horizontal' padding='0,0,0,0' spacing='10'> " +"<space size='20'/> " +"<layout type='horizontal' padding='0,0,0,0' spacing='4'> " "<widget name='Keys' " "type='Button' " "/> " @@ -989,23 +689,15 @@ "</layout> " "</dialog> " "<dialog name='SaveLoadChooser' overlays='screen' inset='8' shading='dim'> " -"<layout type='vertical' padding='8,8,8,32' center='true'> " -"<widget name='Title' " -"height='Globals.Line.Height' " -"/> " -"<layout type='horizontal' padding='0,0,0,16' spacing='16'> " +"<layout type='vertical' padding='8,8,8,8' center='true'> " +"<widget name='Title' height='Globals.Line.Height'/> " "<widget name='List' /> " -"<widget name='Thumbnail' " -"width='180' " -"height='200' " -"/> " -"</layout> " -"<layout type='horizontal' padding='0,0,0,0'> " +"<layout type='horizontal' padding='0,0,16,0'> " "<space/> " "<widget name='Delete' " "type='Button' " "/> " -"<space size='32'/> " +"<space size='16'/> " "<widget name='Cancel' " "type='Button' " "/> " @@ -1015,16 +707,16 @@ "</layout> " "</layout> " "</dialog> " -"<dialog name='ScummHelp' overlays='screen_center'> " -"<layout type='vertical' padding='8,8,8,8' center='true'> " +"<dialog name='ScummHelp' overlays='screen'> " +"<layout type='vertical' padding='8,8,8,8'> " "<widget name='Title' " -"width='320' " +"width='180' " "height='Globals.Line.Height' " "/> " "<widget name='HelpText' " -"height='200' " +"height='140' " "/> " -"<layout type='horizontal' padding='0,0,16,0'> " +"<layout type='horizontal' padding='0,0,0,0'> " "<widget name='Prev' " "type='Button' " "/> " @@ -1039,20 +731,20 @@ "</layout> " "</dialog> " "<dialog name='MassAdd' overlays='screen_center' shading='dim'> " -"<layout type='vertical' padding='8,8,32,8' center='true'> " +"<layout type='vertical' padding='4,4,16,4' center='true'> " "<widget name='DirProgressText' " -"width='480' " +"width='280' " "height='Globals.Line.Height' " "/> " "<widget name='GameProgressText' " -"width='480' " +"width='280' " "height='Globals.Line.Height' " "/> " "<widget name='GameList' " -"width='480' " -"height='250' " +"width='280' " +"height='100' " "/> " -"<layout type='horizontal' padding='8,8,8,8'> " +"<layout type='horizontal' padding='4,4,4,4'> " "<widget name='Ok' " "type='Button' " "/> " @@ -1063,20 +755,20 @@ "</layout> " "</dialog> " "<dialog name='KeyMapper' overlays='screen_center' shading='dim'> " -"<layout type='vertical' padding='8,8,32,8' spacing='10' center='true'> " +"<layout type='vertical' padding='8,8,8,8' spacing='10' center='true'> " "<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='PopupDesc' " "type='OptionsLabel' " "/> " "<widget name='Popup' " "type='PopUp' " -"width='400' " +"width='150' " "height='Globals.Line.Height' " "/> " "</layout> " "<widget name='KeymapArea' " -"width='600' " -"height='280' " +"width='300' " +"height='120' " "/> " "<widget name='Close' " "type='Button' " @@ -1084,40 +776,482 @@ "</layout> " "</dialog> " "</layout_info> " -"<layout_info resolution='320xY,256x240,Xx272'> " +"<render_info> " +"<palette> " +"<color name='black' " +"rgb='0,0,0' " +"/> " +"<color name='lightgrey' " +"rgb='104,104,104' " +"/> " +"<color name='darkgrey' " +"rgb='64,64,64' " +"/> " +"<color name='green' " +"rgb='32,160,32' " +"/> " +"<color name='green2' " +"rgb='0,255,0' " +"/> " +"</palette> " +"<fonts> " +"<font id='text_default' " +"file='helvb12.bdf' " +"/> " +"<font resolution='320xY,256x240' " +"id='text_default' " +"file='clR6x12.bdf' " +"/> " +"<font id='text_button' " +"file='helvb12.bdf' " +"/> " +"<font resolution='320xY,256x240' " +"id='text_button' " +"file='clR6x12.bdf' " +"/> " +"<font id='text_normal' " +"file='helvb12.bdf' " +"/> " +"<font resolution='320xY,256x240' " +"id='text_normal' " +"file='clR6x12.bdf' " +"/> " +"<font id='tooltip_normal' " +"file='fixed5x8.bdf' " +"/> " +"<text_color id='color_normal' " +"color='green' " +"/> " +"<text_color id='color_normal_inverted' " +"color='black' " +"/> " +"<text_color id='color_normal_hover' " +"color='green2' " +"/> " +"<text_color id='color_normal_disabled' " +"color='lightgrey' " +"/> " +"<text_color id='color_alternative' " +"color='lightgrey' " +"/> " +"<text_color id='color_alternative_inverted' " +"color='255,255,255' " +"/> " +"<text_color id='color_alternative_hover' " +"color='176,176,176' " +"/> " +"<text_color id='color_alternative_disabled' " +"color='darkgrey' " +"/> " +"<text_color id='color_button' " +"color='green' " +"/> " +"<text_color id='color_button_hover' " +"color='green2' " +"/> " +"<text_color id='color_button_disabled' " +"color='lightgrey' " +"/> " +"</fonts> " +"<defaults fill='foreground' fg_color='darkgrey' bg_color='black' shadow='0' bevel_color='lightgrey'/> " +"<drawdata id='text_selection' cache='false'> " +"<drawstep func='square' " +"fill='foreground' " +"fg_color='lightgrey' " +"/> " +"</drawdata> " +"<drawdata id='text_selection_focus' cache='false'> " +"<drawstep func='square' " +"fill='foreground' " +"fg_color='green' " +"/> " +"</drawdata> " +"<drawdata id='mainmenu_bg' cache='false'> " +"<drawstep func='fill' " +"fill='foreground' " +"fg_color='black' " +"/> " +"</drawdata> " +"<drawdata id='special_bg' cache='false'> " +"<drawstep func='bevelsq' " +"bevel='2' " +"/> " +"</drawdata> " +"<drawdata id='separator' cache='false'> " +"<drawstep func='square' " +"fill='foreground' " +"height='2' " +"ypos='center' " +"fg_color='lightgrey' " +"/> " +"</drawdata> " +"<drawdata id='scrollbar_base' cache='false'> " +"<drawstep func='bevelsq' " +"bevel='2' " +"/> " +"</drawdata> " +"<drawdata id='scrollbar_handle_hover' cache='false'> " +"<drawstep func='square' " +"fill='foreground' " +"fg_color='green2' " +"/> " +"</drawdata> " +"<drawdata id='scrollbar_handle_idle' cache='false'> " +"<drawstep func='square' " +"fill='foreground' " +"fg_color='green' " +"/> " +"</drawdata> " +"<drawdata id='scrollbar_button_idle' cache='false'> " +"<drawstep func='bevelsq' " +"bevel='2' " +"fill='none' " +"/> " +"<drawstep func='triangle' " +"fg_color='green' " +"fill='foreground' " +"width='auto' " +"height='auto' " +"xpos='center' " +"ypos='center' " +"orientation='top' " +"/> " +"</drawdata> " +"<drawdata id='scrollbar_button_hover' cache='false'> " +"<drawstep func='bevelsq' " +"bevel='2' " +"fill='none' " +"/> " +"<drawstep func='triangle' " +"fg_color='green2' " +"fill='foreground' " +"width='auto' " +"height='auto' " +"xpos='center' " +"ypos='center' " +"orientation='top' " +"/> " +"</drawdata> " +"<drawdata id='tab_active' cache='false'> " +"<text font='text_default' " +"text_color='color_normal_hover' " +"vertical_align='center' " +"horizontal_align='center' " +"/> " +"<drawstep func='tab' " +"bevel='2' " +"radius='0' " +"fill='none' " +"/> " +"</drawdata> " +"<drawdata id='tab_inactive' cache='false'> " +"<text font='text_default' " +"text_color='color_normal' " +"vertical_align='center' " +"horizontal_align='center' " +"/> " +"<drawstep func='tab' " +"bevel='2' " +"radius='0' " +"fill='none' " +"/> " +"</drawdata> " +"<drawdata id='tab_background' cache='false'> " +"</drawdata> " +"<drawdata id='widget_slider' cache='false'> " +"<drawstep func='bevelsq' " +"bevel='2' " +"fill='none' " +"/> " +"</drawdata> " +"<drawdata id='slider_disabled' cache='false'> " +"<drawstep func='square' " +"fill='foreground' " +"fg_color='lightgrey' " +"/> " +"</drawdata> " +"<drawdata id='slider_full' cache='false'> " +"<drawstep func='square' " +"fill='foreground' " +"fg_color='green' " +"/> " +"</drawdata> " +"<drawdata id='slider_hover' cache='false'> " +"<drawstep func='square' " +"fill='foreground' " +"fg_color='green2' " +"/> " +"</drawdata> " +"<drawdata id='widget_small' cache='false'> " +"<drawstep func='bevelsq' " +"bevel='2' " +"fill='none' " +"/> " +"</drawdata> " +"<drawdata id='popup_idle' cache='false'> " +"<drawstep func='bevelsq' " +"bevel='2' " +"fill='none' " +"/> " +"<drawstep func='triangle' " +"fg_color='green' " +"fill='foreground' " +"width='height' " +"height='auto' " +"xpos='right' " +"ypos='center' " +"orientation='bottom' " +"/> " +"<text font='text_default' " +"text_color='color_normal' " +"vertical_align='center' " +"horizontal_align='left' " +"/> " +"</drawdata> " +"<drawdata id='popup_disabled' cache='false'> " +"<drawstep func='bevelsq' " +"bevel='2' " +"fill='none' " +"/> " +"<drawstep func='triangle' " +"fg_color='lightgrey' " +"fill='foreground' " +"width='height' " +"height='auto' " +"xpos='right' " +"ypos='center' " +"orientation='bottom' " +"/> " +"<text font='text_default' " +"text_color='color_normal_disabled' " +"vertical_align='center' " +"horizontal_align='left' " +"/> " +"</drawdata> " +"<drawdata id='popup_hover' cache='false'> " +"<drawstep func='bevelsq' " +"bevel='2' " +"fill='none' " +"/> " +"<drawstep func='triangle' " +"fg_color='green2' " +"fill='foreground' " +"width='height' " +"height='auto' " +"xpos='right' " +"ypos='center' " +"orientation='bottom' " +"/> " +"<text font='text_default' " +"text_color='color_normal_hover' " +"vertical_align='center' " +"horizontal_align='left' " +"/> " +"</drawdata> " +"<drawdata id='widget_textedit' cache='false'> " +"<drawstep func='bevelsq' " +"bevel='2' " +"fill='none' " +"/> " +"</drawdata> " +"<drawdata id='plain_bg' cache='false'> " +"<drawstep func='bevelsq' " +"bevel='2' " +"/> " +"</drawdata> " +"<drawdata id='caret' cache='false'> " +"<drawstep func='square' " +"fill='foreground' " +"fg_color='lightgrey' " +"/> " +"</drawdata> " +"<drawdata id='default_bg' cache='false'> " +"<drawstep func='bevelsq' " +"bevel='2' " +"/> " +"</drawdata> " +"<drawdata id='button_idle' cache='false'> " +"<text font='text_button' " +"text_color='color_button' " +"vertical_align='center' " +"horizontal_align='center' " +"/> " +"<drawstep func='bevelsq' " +"bevel='2' " +"fill='none' " +"/> " +"</drawdata> " +"<drawdata id='button_hover' cache='false'> " +"<text font='text_button' " +"text_color='color_button_hover' " +"vertical_align='center' " +"horizontal_align='center' " +"/> " +"<drawstep func='bevelsq' " +"bevel='2' " +"fill='none' " +"/> " +"</drawdata> " +"<drawdata id='button_disabled' cache='false'> " +"<text font='text_button' " +"text_color='color_button_disabled' " +"vertical_align='center' " +"horizontal_align='center' " +"/> " +"<drawstep func='bevelsq' " +"bevel='2' " +"fill='none' " +"/> " +"</drawdata> " +"<drawdata id='checkbox_disabled' cache='false'> " +"<text font='text_default' " +"text_color='color_normal_disabled' " +"vertical_align='top' " +"horizontal_align='left' " +"/> " +"<drawstep func='bevelsq' " +"bevel='2' " +"fill='none' " +"/> " +"</drawdata> " +"<drawdata id='checkbox_selected' cache='false'> " +"<text font='text_default' " +"text_color='color_normal' " +"vertical_align='top' " +"horizontal_align='left' " +"/> " +"<drawstep func='bevelsq' " +"bevel='2' " +"fill='none' " +"/> " +"<drawstep func='cross' " +"fill='foreground' " +"stroke='2' " +"fg_color='green' " +"/> " +"</drawdata> " +"<drawdata id='checkbox_default' cache='false'> " +"<text font='text_default' " +"text_color='color_normal' " +"vertical_align='top' " +"horizontal_align='left' " +"/> " +"<drawstep func='bevelsq' " +"bevel='2' " +"fill='none' " +"/> " +"</drawdata> " +"<drawdata id='radiobutton_default' cache='false'> " +"<text font='text_default' " +"text_color='color_normal' " +"vertical_align='center' " +"horizontal_align='left' " +"/> " +"<drawstep func='circle' " +"width='7' " +"height='7' " +"radius='7' " +"fill='background' " +"bg_color='darkgrey' " +"xpos='0' " +"ypos='0' " +"/> " +"</drawdata> " +"<drawdata id='radiobutton_selected' cache='false'> " +"<text font='text_default' " +"text_color='color_normal' " +"vertical_align='center' " +"horizontal_align='left' " +"/> " +"<drawstep func='circle' " +"width='7' " +"height='7' " +"radius='7' " +"fg_color='darkgrey' " +"fill='none' " +"xpos='0' " +"ypos='0' " +"/> " +"<drawstep func='circle' " +"width='7' " +"height='7' " +"radius='5' " +"fg_color='green' " +"fill='foreground' " +"xpos='2' " +"ypos='2' " +"/> " +"</drawdata> " +"<drawdata id='radiobutton_disabled' cache='false'> " +"<text font='text_default' " +"text_color='color_normal_disabled' " +"vertical_align='center' " +"horizontal_align='left' " +"/> " +"<drawstep func='circle' " +"width='7' " +"height='7' " +"radius='7' " +"bg_color='lightgrey' " +"fill='background' " +"xpos='0' " +"ypos='0' " +"/> " +"</drawdata> " +"<drawdata id='widget_default' cache='false'> " +"<drawstep func='bevelsq' " +"bevel='2' " +"/> " +"</drawdata> " +"<drawdata id='widget_small' cache='false'> " +"<drawstep func='square' " +"stroke='0' " +"/> " +"</drawdata> " +"</render_info> " +"<layout_info resolution='-320xY,-256x240,-Xx272'> " "<globals> " -"<def var='Line.Height' value='12' /> " -"<def var='Font.Height' value='10' /> " -"<def var='About.OuterBorder' value='10'/> " -"<def var='Layout.Spacing' value='8'/> " +"<def var='Line.Height' value='16' /> " +"<def var='Font.Height' value='16' /> " +"<def var='About.OuterBorder' value='80'/> " +"<def var='Layout.Spacing' value='8' /> " "<def var='ShowLauncherLogo' value='0'/> " "<def var='ShowGlobalMenuLogo' value='0'/> " "<def var='ShowSearchPic' value='0'/> " -"<def var='SaveLoadChooser.ExtInfo.Visible' value='0'/> " -"<def var='KeyMapper.Spacing' value='5'/> " -"<def var='KeyMapper.LabelWidth' value='80'/> " -"<def var='KeyMapper.ButtonWidth' value='60'/> " -"<widget name='Button' " -"size='72,16' " -"/> " -"<widget name='Slider' " -"size='85,12' " -"/> " +"<def var='SaveLoadChooser.ExtInfo.Visible' value='1'/> " +"<def var='KeyMapper.Spacing' value='10'/> " +"<def var='KeyMapper.LabelWidth' value='100'/> " +"<def var='KeyMapper.ButtonWidth' value='80'/> " +"<def var='Tooltip.MaxWidth' value='200'/> " +"<def var='Tooltip.XDelta' value='16'/> " +"<def var='Tooltip.YDelta' value='16'/> " "<widget name='OptionsLabel' " "size='110,Globals.Line.Height' " "textalign='right' " "/> " "<widget name='SmallLabel' " -"size='18,Globals.Line.Height' " +"size='24,Globals.Line.Height' " +"/> " +"<widget name='ShortOptionsLabel' " +"size='60,Globals.Line.Height' " +"/> " +"<widget name='Button' " +"size='108,24' " +"/> " +"<widget name='Slider' " +"size='128,18' " "/> " "<widget name='PopUp' " -"size='-1,15' " +"size='-1,19' " "/> " "<widget name='Checkbox' " +"size='-1,14' " +"/> " +"<widget name='Radiobutton' " "size='-1,Globals.Line.Height' " "/> " "<widget name='ListWidget' " -"padding='5,0,0,0' " +"padding='5,0,8,0' " "/> " "<widget name='PopUpWidget' " "padding='7,5,0,0' " @@ -1129,25 +1263,28 @@ "padding='7,5,5,5' " "/> " "<widget name='Scrollbar' " -"size='9,0' " +"size='15,0' " "/> " "<widget name='TabWidget.Tab' " -"size='45,16' " -"padding='0,0,2,0' " +"size='75,27' " +"padding='0,0,8,0' " +"/> " +"<widget name='TabWidget.Body' " +"padding='0,0,0,0' " "/> " "<widget name='TabWidget.NavButton' " -"size='32,18' " +"size='15,18' " "padding='0,3,4,0' " "/> " "</globals> " "<dialog name='Launcher' overlays='screen'> " -"<layout type='vertical' center='true' padding='8,8,4,4'> " +"<layout type='vertical' center='true' padding='16,16,8,8'> " "<widget name='Version' " "height='Globals.Line.Height' " "/> " "<layout type='horizontal' spacing='5' padding='10,0,0,0'> " "<widget name='SearchDesc' " -"width='50' " +"width='60' " "height='Globals.Line.Height' " "textalign='right' " "/> " @@ -1164,36 +1301,37 @@ "<widget name='GameList'/> " "<layout type='horizontal' padding='0,0,0,0' spacing='10'> " "<widget name='LoadGameButton' " -"height='12' " +"height='20' " "/> " "<widget name='AddGameButton' " -"height='12' " +"height='20' " "/> " "<widget name='EditGameButton' " -"height='12' " +"height='20' " "/> " "<widget name='RemoveGameButton' " -"height='12' " +"height='20' " "/> " "</layout> " +"<space size='4'/> " "<layout type='horizontal' padding='0,0,0,0' spacing='10'> " "<widget name='QuitButton' " -"height='12' " +"height='20' " "/> " "<widget name='AboutButton' " -"height='12' " +"height='20' " "/> " "<widget name='OptionsButton' " -"height='12' " +"height='20' " "/> " "<widget name='StartButton' " -"height='12' " +"height='20' " "/> " "</layout> " "</layout> " "</dialog> " -"<dialog name='Browser' overlays='screen' inset='8' shading='dim'> " -"<layout type='vertical' padding='8,8,0,4'> " +"<dialog name='Browser' overlays='Dialog.Launcher.GameList' shading='dim'> " +"<layout type='vertical' padding='8,8,8,8'> " "<widget name='Headline' " "height='Globals.Line.Height' " "/> " @@ -1201,7 +1339,7 @@ "height='Globals.Line.Height' " "/> " "<widget name='List'/> " -"<layout type='horizontal' padding='0,0,8,0'> " +"<layout type='horizontal' padding='0,0,16,0'> " "<widget name='Up' " "type='Button' " "/> " @@ -1215,10 +1353,10 @@ "</layout> " "</layout> " "</dialog> " -"<dialog name='GlobalOptions' overlays='screen' inset='16' shading='dim'> " +"<dialog name='GlobalOptions' overlays='Dialog.Launcher.GameList' shading='dim'> " "<layout type='vertical' padding='0,0,0,0'> " "<widget name='TabWidget'/> " -"<layout type='horizontal' padding='8,8,8,8'> " +"<layout type='horizontal' padding='16,16,16,16'> " "<space/> " "<widget name='Cancel' " "type='Button' " @@ -1231,7 +1369,7 @@ "</dialog> " "<dialog name='GlobalOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> " "<layout type='vertical' padding='16,16,16,16' spacing='8'> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='grModePopupDesc' " "type='OptionsLabel' " "/> " @@ -1239,7 +1377,7 @@ "type='PopUp' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='grRenderPopupDesc' " "type='OptionsLabel' " "/> " @@ -1257,7 +1395,7 @@ "</dialog> " "<dialog name='GlobalOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> " "<layout type='vertical' padding='16,16,16,16' spacing='8'> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='auMidiPopupDesc' " "type='OptionsLabel' " "/> " @@ -1265,7 +1403,23 @@ "type='PopUp' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<widget name='auPrefMt32PopupDesc' " +"type='OptionsLabel' " +"/> " +"<widget name='auPrefMt32Popup' " +"type='PopUp' " +"/> " +"</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<widget name='auPrefGmPopupDesc' " +"type='OptionsLabel' " +"/> " +"<widget name='auPrefGmPopup' " +"type='PopUp' " +"/> " +"</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='auOPLPopupDesc' " "type='OptionsLabel' " "/> " @@ -1273,7 +1427,7 @@ "type='PopUp' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='auSampleRatePopupDesc' " "type='OptionsLabel' " "/> " @@ -1281,16 +1435,21 @@ "type='PopUp' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10'> " "<widget name='subToggleDesc' " "type='OptionsLabel' " "/> " -"<widget name='subToggleButton' " -"width='128' " -"height='Globals.Slider.Height' " +"<widget name='subToggleSpeechOnly' " +"type='Radiobutton' " +"/> " +"<widget name='subToggleSubOnly' " +"type='Radiobutton' " +"/> " +"<widget name='subToggleSubBoth' " +"type='Radiobutton' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10'> " "<widget name='subSubtitleSpeedDesc' " "type='OptionsLabel' " "/> " @@ -1304,8 +1463,9 @@ "</layout> " "</dialog> " "<dialog name='GlobalOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> " -"<layout type='vertical' padding='16,16,16,16' spacing='8'> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='16,16,16,16' spacing='8'> " +"<layout type='vertical' padding='0,0,0,0' spacing='8'> " +"<layout type='horizontal' padding='0,0,0,0'> " "<widget name='vcMusicText' " "type='OptionsLabel' " "/> " @@ -1316,7 +1476,7 @@ "type='SmallLabel' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0'> " "<widget name='vcSfxText' " "type='OptionsLabel' " "/> " @@ -1327,7 +1487,7 @@ "type='SmallLabel' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0'> " "<widget name='vcSpeechText' " "type='OptionsLabel' " "/> " @@ -1338,8 +1498,8 @@ "type='SmallLabel' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " -"<space size='110' /> " +"</layout> " +"<layout type='vertical' padding='24,0,24,0' center='true'> " "<widget name='vcMuteCheckbox' " "type='Checkbox' " "/> " @@ -1348,7 +1508,7 @@ "</dialog> " "<dialog name='GlobalOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> " "<layout type='vertical' padding='16,16,16,16' spacing='8'> " -"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='mcFontButton' " "type='Button' " "/> " @@ -1369,7 +1529,7 @@ "<widget name='mcGSCheckbox' " "type='Checkbox' " "/> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0'> " "<widget name='mcMidiGainText' " "type='OptionsLabel' " "/> " @@ -1385,7 +1545,7 @@ "</dialog> " "<dialog name='GlobalOptions_Paths' overlays='Dialog.GlobalOptions.TabWidget'> " "<layout type='vertical' padding='16,16,16,16' spacing='8'> " -"<layout type='horizontal' padding='0,0,0,0' spacing='16'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='SaveButton' " "type='Button' " "/> " @@ -1393,7 +1553,7 @@ "height='Globals.Line.Height' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='16'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='ThemeButton' " "type='Button' " "/> " @@ -1401,7 +1561,7 @@ "height='Globals.Line.Height' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='16'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='ExtraButton' " "type='Button' " "/> " @@ -1421,7 +1581,7 @@ "</dialog> " "<dialog name='GlobalOptions_Misc' overlays='Dialog.GlobalOptions.TabWidget'> " "<layout type='vertical' padding='16,16,16,16' spacing='8'> " -"<layout type='horizontal' padding='0,0,0,0' spacing='16'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='ThemeButton' " "type='Button' " "/> " @@ -1429,26 +1589,30 @@ "height='Globals.Line.Height' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='RendererPopupDesc' " -"width='80' " -"height='Globals.Line.Height' " -"textalign='right' " +"type='OptionsLabel' " "/> " "<widget name='RendererPopup' " "type='PopUp' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='AutosavePeriodPopupDesc' " -"width='80' " -"height='Globals.Line.Height' " -"textalign='right' " +"type='OptionsLabel' " "/> " "<widget name='AutosavePeriodPopup' " "type='PopUp' " "/> " "</layout> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " +"<widget name='GuiLanguagePopupDesc' " +"type='OptionsLabel' " +"/> " +"<widget name='GuiLanguagePopup' " +"type='PopUp' " +"/> " +"</layout> " "<widget name='KeysButton' " "type='Button' " "/> " @@ -1478,10 +1642,10 @@ "</layout> " "</layout> " "</dialog> " -"<dialog name='GameOptions' overlays='screen' inset='16' shading='dim'> " +"<dialog name='GameOptions' overlays='Dialog.Launcher.GameList' shading='dim'> " "<layout type='vertical' padding='0,0,0,0' spacing='16'> " "<widget name='TabWidget'/> " -"<layout type='horizontal' padding='8,8,8,8'> " +"<layout type='horizontal' padding='16,16,16,4'> " "<space/> " "<widget name='Cancel' " "type='Button' " @@ -1493,7 +1657,7 @@ "</layout> " "</dialog> " "<dialog name='GameOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> " -"<layout type='vertical' padding='8,8,8,8' spacing='6'> " +"<layout type='vertical' padding='16,16,16,16' spacing='8'> " "<widget name='EnableTabCheckbox' " "type='Checkbox' " "/> " @@ -1501,7 +1665,7 @@ "</layout> " "</dialog> " "<dialog name='GameOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> " -"<layout type='vertical' padding='8,8,8,8' spacing='6'> " +"<layout type='vertical' padding='16,16,16,16' spacing='8'> " "<widget name='EnableTabCheckbox' " "type='Checkbox' " "/> " @@ -1509,7 +1673,7 @@ "</layout> " "</dialog> " "<dialog name='GameOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> " -"<layout type='vertical' padding='8,8,8,8' spacing='6'> " +"<layout type='vertical' padding='16,16,16,16' spacing='8'> " "<widget name='EnableTabCheckbox' " "type='Checkbox' " "/> " @@ -1517,7 +1681,7 @@ "</layout> " "</dialog> " "<dialog name='GameOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> " -"<layout type='vertical' padding='8,8,8,8' spacing='6'> " +"<layout type='vertical' padding='16,16,16,16' spacing='8'> " "<widget name='EnableTabCheckbox' " "type='Checkbox' " "/> " @@ -1525,43 +1689,34 @@ "</layout> " "</dialog> " "<dialog name='GameOptions_Game' overlays='Dialog.GameOptions.TabWidget' shading='dim'> " -"<layout type='vertical' padding='8,8,8,8'> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='vertical' padding='16,16,16,16'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='Id' " -"width='35' " -"height='Globals.Line.Height' " -"textalign='right' " +"type='OptionsLabel' " "/> " "<widget name='Domain' " "type='PopUp' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='Name' " -"width='35' " -"height='Globals.Line.Height' " -"textalign='right' " +"type='OptionsLabel' " "/> " "<widget name='Desc' " "type='PopUp' " "/> " "</layout> " -"<space size='8'/> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='LangPopupDesc' " -"width='60' " -"height='Globals.Line.Height' " -"textalign='right' " +"type='OptionsLabel' " "/> " "<widget name='LangPopup' " "type='PopUp' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='PlatformPopupDesc' " -"width='60' " -"height='Globals.Line.Height' " -"textalign='right' " +"type='OptionsLabel' " "/> " "<widget name='PlatformPopup' " "type='PopUp' " @@ -1570,8 +1725,8 @@ "</layout> " "</dialog> " "<dialog name='GameOptions_Paths' overlays='Dialog.GameOptions.TabWidget' shading='dim'> " -"<layout type='vertical' padding='8,8,8,8'> " -"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> " +"<layout type='vertical' padding='16,16,16,16'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='Savepath' " "type='Button' " "/> " @@ -1579,7 +1734,7 @@ "height='Globals.Line.Height' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='Extrapath' " "type='Button' " "/> " @@ -1587,7 +1742,7 @@ "height='Globals.Line.Height' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='Gamepath' " "type='Button' " "/> " @@ -1598,55 +1753,57 @@ "</layout> " "</dialog> " "<dialog name='GlobalMenu' overlays='screen_center'> " -"<layout type='vertical' padding='2,2,4,6' center='true' spacing='6'> " +"<layout type='vertical' padding='16,16,16,16' center='true'> " "<widget name='Title' " -"width='160' " -"height='4' " +"width='210' " +"height='Globals.Line.Height' " "/> " "<widget name='Version' " -"width='160' " -"height='4' " +"width='210' " +"height='Globals.Line.Height' " "/> " -"<space size='1'/> " +"<widget name='Resume' " +"width='150' " +"height='Globals.Button.Height' " +"/> " +"<space size='10'/> " "<widget name='Load' " -"width='120' " -"height='12' " +"width='150' " +"height='Globals.Button.Height' " "/> " "<widget name='Save' " -"width='120' " -"height='12' " +"width='150' " +"height='Globals.Button.Height' " "/> " -"<space size='1'/> " +"<space size='10'/> " "<widget name='Options' " -"width='120' " -"height='12' " +"width='150' " +"height='Globals.Button.Height' " "/> " "<widget name='Help' " -"width='120' " -"height='12' " +"width='150' " +"height='Globals.Button.Height' " "/> " "<widget name='About' " -"width='120' " -"height='12' " -"/> " -"<space size='1'/> " -"<widget name='Resume' " -"width='120' " -"height='12' " +"width='150' " +"height='Globals.Button.Height' " "/> " +"<space size='10'/> " "<widget name='RTL' " -"width='120' " -"height='12' " +"width='150' " +"height='Globals.Button.Height' " "/> " "<widget name='Quit' " -"width='120' " -"height='12' " +"width='150' " +"height='Globals.Button.Height' " "/> " "</layout> " "</dialog> " "<dialog name='GlobalConfig' overlays='screen_center'> " "<layout type='vertical' padding='8,8,8,8'> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0'> " +"<layout type='vertical' padding='0,0,0,0' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='8'> " "<widget name='vcMusicText' " "type='OptionsLabel' " "/> " @@ -1657,7 +1814,7 @@ "type='SmallLabel' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='8'> " "<widget name='vcSfxText' " "type='OptionsLabel' " "/> " @@ -1668,7 +1825,7 @@ "type='SmallLabel' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='8'> " "<widget name='vcSpeechText' " "type='OptionsLabel' " "/> " @@ -1679,24 +1836,33 @@ "type='SmallLabel' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " -"<space size='110' /> " +"</layout> " +"<layout type='vertical' padding='24,24,24,24' center='true'> " "<widget name='vcMuteCheckbox' " "type='Checkbox' " -"width='80' " +"width='80' " "/> " "</layout> " -"<space size='4' /> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"</layout> " +"<space size='8' /> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10'> " "<widget name='subToggleDesc' " "type='OptionsLabel' " "/> " -"<widget name='subToggleButton' " -"width='128' " -"height='Globals.Slider.Height' " +"<widget name='subToggleSpeechOnly' " +"type='Radiobutton' " +"width='100' " +"/> " +"<widget name='subToggleSubOnly' " +"type='Radiobutton' " +"width='100' " +"/> " +"<widget name='subToggleSubBoth' " +"type='Radiobutton' " +"width='100' " "/> " "</layout> " -"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10'> " "<widget name='subSubtitleSpeedDesc' " "type='OptionsLabel' " "/> " @@ -1707,8 +1873,8 @@ "type='SmallLabel' " "/> " "</layout> " -"<space size='20'/> " -"<layout type='horizontal' padding='0,0,0,0' spacing='4'> " +"<space size='60'/> " +"<layout type='horizontal' padding='0,0,0,0' spacing='10'> " "<widget name='Keys' " "type='Button' " "/> " @@ -1723,15 +1889,23 @@ "</layout> " "</dialog> " "<dialog name='SaveLoadChooser' overlays='screen' inset='8' shading='dim'> " -"<layout type='vertical' padding='8,8,8,8' center='true'> " -"<widget name='Title' height='Globals.Line.Height'/> " +"<layout type='vertical' padding='8,8,8,32' center='true'> " +"<widget name='Title' " +"height='Globals.Line.Height' " +"/> " +"<layout type='horizontal' padding='0,0,0,16' spacing='16'> " "<widget name='List' /> " -"<layout type='horizontal' padding='0,0,16,0'> " +"<widget name='Thumbnail' " +"width='180' " +"height='200' " +"/> " +"</layout> " +"<layout type='horizontal' padding='0,0,0,0'> " "<space/> " "<widget name='Delete' " "type='Button' " "/> " -"<space size='16'/> " +"<space size='32'/> " "<widget name='Cancel' " "type='Button' " "/> " @@ -1741,16 +1915,16 @@ "</layout> " "</layout> " "</dialog> " -"<dialog name='ScummHelp' overlays='screen'> " -"<layout type='vertical' padding='8,8,8,8'> " +"<dialog name='ScummHelp' overlays='screen_center'> " +"<layout type='vertical' padding='8,8,8,8' center='true'> " "<widget name='Title' " -"width='180' " +"width='320' " "height='Globals.Line.Height' " "/> " "<widget name='HelpText' " -"height='140' " +"height='200' " "/> " -"<layout type='horizontal' padding='0,0,0,0'> " +"<layout type='horizontal' padding='0,0,16,0'> " "<widget name='Prev' " "type='Button' " "/> " @@ -1765,20 +1939,20 @@ "</layout> " "</dialog> " "<dialog name='MassAdd' overlays='screen_center' shading='dim'> " -"<layout type='vertical' padding='4,4,16,4' center='true'> " +"<layout type='vertical' padding='8,8,32,8' center='true'> " "<widget name='DirProgressText' " -"width='280' " +"width='480' " "height='Globals.Line.Height' " "/> " "<widget name='GameProgressText' " -"width='280' " +"width='480' " "height='Globals.Line.Height' " "/> " "<widget name='GameList' " -"width='280' " -"height='100' " +"width='480' " +"height='250' " "/> " -"<layout type='horizontal' padding='4,4,4,4'> " +"<layout type='horizontal' padding='8,8,8,8'> " "<widget name='Ok' " "type='Button' " "/> " @@ -1789,20 +1963,20 @@ "</layout> " "</dialog> " "<dialog name='KeyMapper' overlays='screen_center' shading='dim'> " -"<layout type='vertical' padding='8,8,8,8' spacing='10' center='true'> " +"<layout type='vertical' padding='8,8,32,8' spacing='10' center='true'> " "<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> " "<widget name='PopupDesc' " "type='OptionsLabel' " "/> " "<widget name='Popup' " "type='PopUp' " -"width='150' " +"width='400' " "height='Globals.Line.Height' " "/> " "</layout> " "<widget name='KeymapArea' " -"width='300' " -"height='120' " +"width='600' " +"height='280' " "/> " "<widget name='Close' " "type='Button' " diff --git a/gui/themes/fonts/Arial.bdf b/gui/themes/fonts/Arial.bdf new file mode 100644 index 0000000000..8c2d2f264a --- /dev/null +++ b/gui/themes/fonts/Arial.bdf @@ -0,0 +1,1537 @@ +STARTFONT 2.1 +COMMENT +COMMENT Converted from TrueType font "arial.ttf" by "ttf2bdf 2.8". +COMMENT +FONT -FreeType-Arial-Medium-R-Normal--12-120-75-75-P-57-ISO10646-1 +SIZE 12 75 75 +FONTBOUNDINGBOX 14 13 -1 -3 +STARTPROPERTIES 19 +FOUNDRY "FreeType" +FAMILY_NAME "Arial" +WEIGHT_NAME "Medium" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 12 +POINT_SIZE 120 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "P" +AVERAGE_WIDTH 57 +CHARSET_REGISTRY "ISO10646" +CHARSET_ENCODING "1" +FONT_ASCENT 11 +FONT_DESCENT 2 +COPYRIGHT "Typeface © The Monotype Corporation plc. Data © The Monotype Corporation plc/Type Solutions Inc. 1990-1992. All Rights Reserved" +_TTF_FONTFILE "arial.ttf" +_TTF_PSNAME "ArialMT" +ENDPROPERTIES +CHARS 96 +STARTCHAR 0020 +ENCODING 32 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR 0021 +ENCODING 33 +SWIDTH 240 0 +DWIDTH 3 0 +BBX 1 10 1 0 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +00 +80 +ENDCHAR +STARTCHAR 0022 +ENCODING 34 +SWIDTH 400 0 +DWIDTH 5 0 +BBX 3 3 1 7 +BITMAP +A0 +A0 +A0 +ENDCHAR +STARTCHAR 0023 +ENCODING 35 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +12 +12 +14 +FF +24 +24 +FF +48 +48 +48 +ENDCHAR +STARTCHAR 0024 +ENCODING 36 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 11 1 -1 +BITMAP +70 +A8 +A0 +A0 +E0 +38 +28 +A8 +A8 +70 +20 +ENDCHAR +STARTCHAR 0025 +ENCODING 37 +SWIDTH 960 0 +DWIDTH 12 0 +BBX 10 10 1 0 +BITMAP +6100 +9200 +9200 +9400 +6400 +0980 +0A40 +1240 +1240 +2180 +ENDCHAR +STARTCHAR 0026 +ENCODING 38 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 8 10 1 0 +BITMAP +30 +48 +48 +48 +30 +60 +92 +8A +8C +73 +ENDCHAR +STARTCHAR 0027 +ENCODING 39 +SWIDTH 160 0 +DWIDTH 2 0 +BBX 1 3 1 7 +BITMAP +80 +80 +80 +ENDCHAR +STARTCHAR 0028 +ENCODING 40 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 3 13 1 -3 +BITMAP +20 +40 +40 +80 +80 +80 +80 +80 +80 +80 +40 +40 +20 +ENDCHAR +STARTCHAR 0029 +ENCODING 41 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 3 13 0 -3 +BITMAP +80 +40 +40 +20 +20 +20 +20 +20 +20 +20 +40 +40 +80 +ENDCHAR +STARTCHAR 002A +ENCODING 42 +SWIDTH 400 0 +DWIDTH 5 0 +BBX 5 4 0 6 +BITMAP +20 +F8 +20 +50 +ENDCHAR +STARTCHAR 002B +ENCODING 43 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 7 7 1 1 +BITMAP +10 +10 +10 +FE +10 +10 +10 +ENDCHAR +STARTCHAR 002C +ENCODING 44 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 1 3 2 -2 +BITMAP +80 +80 +80 +ENDCHAR +STARTCHAR 002D +ENCODING 45 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 3 1 0 3 +BITMAP +E0 +ENDCHAR +STARTCHAR 002E +ENCODING 46 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 1 1 1 0 +BITMAP +80 +ENDCHAR +STARTCHAR 002F +ENCODING 47 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 4 10 0 0 +BITMAP +10 +10 +20 +20 +20 +40 +40 +40 +80 +80 +ENDCHAR +STARTCHAR 0030 +ENCODING 48 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +78 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR 0031 +ENCODING 49 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 3 10 1 0 +BITMAP +20 +60 +A0 +20 +20 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR 0032 +ENCODING 50 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +78 +84 +04 +04 +04 +08 +10 +20 +40 +FC +ENDCHAR +STARTCHAR 0033 +ENCODING 51 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +78 +84 +04 +04 +38 +04 +04 +04 +84 +78 +ENDCHAR +STARTCHAR 0034 +ENCODING 52 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +08 +18 +18 +28 +28 +48 +48 +FC +08 +08 +ENDCHAR +STARTCHAR 0035 +ENCODING 53 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +7C +40 +40 +80 +F8 +84 +04 +04 +84 +78 +ENDCHAR +STARTCHAR 0036 +ENCODING 54 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +78 +84 +80 +80 +B8 +C4 +84 +84 +84 +78 +ENDCHAR +STARTCHAR 0037 +ENCODING 55 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +FC +08 +08 +10 +10 +20 +20 +40 +40 +40 +ENDCHAR +STARTCHAR 0038 +ENCODING 56 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +78 +84 +84 +84 +78 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR 0039 +ENCODING 57 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +78 +84 +84 +84 +8C +74 +04 +04 +88 +70 +ENDCHAR +STARTCHAR 003A +ENCODING 58 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 1 7 1 0 +BITMAP +80 +00 +00 +00 +00 +00 +80 +ENDCHAR +STARTCHAR 003B +ENCODING 59 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 1 9 1 -2 +BITMAP +80 +00 +00 +00 +00 +00 +80 +80 +80 +ENDCHAR +STARTCHAR 003C +ENCODING 60 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 7 1 1 +BITMAP +04 +18 +60 +80 +60 +18 +04 +ENDCHAR +STARTCHAR 003D +ENCODING 61 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 7 4 0 3 +BITMAP +FE +00 +00 +FE +ENDCHAR +STARTCHAR 003E +ENCODING 62 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 7 1 1 +BITMAP +80 +60 +18 +04 +18 +60 +80 +ENDCHAR +STARTCHAR 003F +ENCODING 63 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +70 +88 +88 +08 +10 +20 +40 +40 +00 +40 +ENDCHAR +STARTCHAR 0040 +ENCODING 64 +SWIDTH 1040 0 +DWIDTH 13 0 +BBX 12 13 0 -3 +BITMAP +0F80 +3040 +4020 +4E90 +9190 +A090 +A110 +A120 +A320 +9DC0 +4010 +2060 +1F80 +ENDCHAR +STARTCHAR 0041 +ENCODING 65 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 9 10 0 0 +BITMAP +0800 +1400 +1400 +3600 +2200 +2200 +7F00 +4100 +8080 +8080 +ENDCHAR +STARTCHAR 0042 +ENCODING 66 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +FC +82 +82 +82 +FC +82 +82 +82 +82 +FC +ENDCHAR +STARTCHAR 0043 +ENCODING 67 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +38 +44 +82 +80 +80 +80 +80 +82 +44 +38 +ENDCHAR +STARTCHAR 0044 +ENCODING 68 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +F8 +84 +82 +82 +82 +82 +82 +82 +84 +F8 +ENDCHAR +STARTCHAR 0045 +ENCODING 69 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +FE +80 +80 +80 +FE +80 +80 +80 +80 +FE +ENDCHAR +STARTCHAR 0046 +ENCODING 70 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 10 1 0 +BITMAP +FC +80 +80 +80 +F8 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR 0047 +ENCODING 71 +SWIDTH 800 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +3C +42 +81 +80 +80 +8F +81 +81 +42 +3C +ENDCHAR +STARTCHAR 0048 +ENCODING 72 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +82 +82 +82 +82 +FE +82 +82 +82 +82 +82 +ENDCHAR +STARTCHAR 0049 +ENCODING 73 +SWIDTH 240 0 +DWIDTH 3 0 +BBX 1 10 1 0 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR 004A +ENCODING 74 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 5 10 0 0 +BITMAP +08 +08 +08 +08 +08 +08 +08 +88 +88 +70 +ENDCHAR +STARTCHAR 004B +ENCODING 75 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 8 10 1 0 +BITMAP +81 +82 +84 +88 +90 +B0 +C8 +84 +82 +81 +ENDCHAR +STARTCHAR 004C +ENCODING 76 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 1 0 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +FC +ENDCHAR +STARTCHAR 004D +ENCODING 77 +SWIDTH 880 0 +DWIDTH 11 0 +BBX 9 10 1 0 +BITMAP +8080 +C180 +C180 +A280 +A280 +9680 +9480 +9480 +8880 +8880 +ENDCHAR +STARTCHAR 004E +ENCODING 78 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +82 +C2 +A2 +A2 +92 +92 +8A +8A +86 +82 +ENDCHAR +STARTCHAR 004F +ENCODING 79 +SWIDTH 800 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +3C +42 +81 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR 0050 +ENCODING 80 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +FC +82 +82 +82 +82 +FC +80 +80 +80 +80 +ENDCHAR +STARTCHAR 0051 +ENCODING 81 +SWIDTH 800 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +3C +42 +81 +81 +81 +81 +81 +8D +42 +3D +ENDCHAR +STARTCHAR 0052 +ENCODING 82 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +FC +82 +82 +82 +82 +FC +88 +84 +84 +82 +ENDCHAR +STARTCHAR 0053 +ENCODING 83 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +7C +82 +82 +80 +70 +0C +02 +82 +82 +7C +ENDCHAR +STARTCHAR 0054 +ENCODING 84 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +FE +10 +10 +10 +10 +10 +10 +10 +10 +10 +ENDCHAR +STARTCHAR 0055 +ENCODING 85 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +82 +82 +82 +82 +82 +82 +82 +82 +44 +38 +ENDCHAR +STARTCHAR 0056 +ENCODING 86 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 9 10 0 0 +BITMAP +8080 +8080 +4100 +4100 +2200 +2200 +1400 +1400 +0800 +0800 +ENDCHAR +STARTCHAR 0057 +ENCODING 87 +SWIDTH 1040 0 +DWIDTH 13 0 +BBX 13 10 0 0 +BITMAP +8208 +8508 +4510 +4510 +4510 +28A0 +28A0 +28A0 +1040 +1040 +ENDCHAR +STARTCHAR 0058 +ENCODING 88 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +82 +44 +24 +28 +10 +10 +28 +28 +44 +82 +ENDCHAR +STARTCHAR 0059 +ENCODING 89 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +82 +44 +44 +28 +28 +10 +10 +10 +10 +10 +ENDCHAR +STARTCHAR 005A +ENCODING 90 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +7E +04 +08 +08 +10 +10 +20 +20 +40 +FE +ENDCHAR +STARTCHAR 005B +ENCODING 91 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 2 13 1 -3 +BITMAP +C0 +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +C0 +ENDCHAR +STARTCHAR 005C +ENCODING 92 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 4 10 0 0 +BITMAP +80 +80 +40 +40 +40 +20 +20 +20 +10 +10 +ENDCHAR +STARTCHAR 005D +ENCODING 93 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 2 13 1 -3 +BITMAP +C0 +40 +40 +40 +40 +40 +40 +40 +40 +40 +40 +40 +C0 +ENDCHAR +STARTCHAR 005E +ENCODING 94 +SWIDTH 400 0 +DWIDTH 5 0 +BBX 5 5 0 4 +BITMAP +20 +50 +50 +50 +88 +ENDCHAR +STARTCHAR 005F +ENCODING 95 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 7 1 0 -3 +BITMAP +FE +ENDCHAR +STARTCHAR 0060 +ENCODING 96 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 2 2 1 8 +BITMAP +80 +40 +ENDCHAR +STARTCHAR 0061 +ENCODING 97 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +70 +88 +08 +78 +88 +98 +68 +ENDCHAR +STARTCHAR 0062 +ENCODING 98 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +80 +80 +80 +B0 +C8 +88 +88 +88 +C8 +B0 +ENDCHAR +STARTCHAR 0063 +ENCODING 99 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +70 +88 +80 +80 +80 +88 +70 +ENDCHAR +STARTCHAR 0064 +ENCODING 100 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +08 +08 +08 +68 +98 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR 0065 +ENCODING 101 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR 0066 +ENCODING 102 +SWIDTH 240 0 +DWIDTH 3 0 +BBX 4 10 0 0 +BITMAP +30 +40 +40 +E0 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR 0067 +ENCODING 103 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +68 +98 +88 +88 +88 +98 +68 +08 +88 +70 +ENDCHAR +STARTCHAR 0068 +ENCODING 104 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +80 +80 +80 +B0 +C8 +88 +88 +88 +88 +88 +ENDCHAR +STARTCHAR 0069 +ENCODING 105 +SWIDTH 240 0 +DWIDTH 3 0 +BBX 1 10 1 0 +BITMAP +80 +00 +00 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR 006A +ENCODING 106 +SWIDTH 240 0 +DWIDTH 3 0 +BBX 3 13 -1 -3 +BITMAP +20 +00 +00 +20 +20 +20 +20 +20 +20 +20 +20 +20 +C0 +ENDCHAR +STARTCHAR 006B +ENCODING 107 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +80 +80 +80 +88 +90 +A0 +E0 +90 +90 +88 +ENDCHAR +STARTCHAR 006C +ENCODING 108 +SWIDTH 240 0 +DWIDTH 3 0 +BBX 1 10 1 0 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR 006D +ENCODING 109 +SWIDTH 880 0 +DWIDTH 11 0 +BBX 9 7 1 0 +BITMAP +B300 +CC80 +8880 +8880 +8880 +8880 +8880 +ENDCHAR +STARTCHAR 006E +ENCODING 110 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +B0 +C8 +88 +88 +88 +88 +88 +ENDCHAR +STARTCHAR 006F +ENCODING 111 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR 0070 +ENCODING 112 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +B0 +C8 +88 +88 +88 +C8 +B0 +80 +80 +80 +ENDCHAR +STARTCHAR 0071 +ENCODING 113 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +68 +98 +88 +88 +88 +98 +68 +08 +08 +08 +ENDCHAR +STARTCHAR 0072 +ENCODING 114 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 3 7 1 0 +BITMAP +A0 +C0 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR 0073 +ENCODING 115 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +70 +88 +80 +70 +08 +88 +70 +ENDCHAR +STARTCHAR 0074 +ENCODING 116 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 3 9 0 0 +BITMAP +40 +40 +E0 +40 +40 +40 +40 +40 +60 +ENDCHAR +STARTCHAR 0075 +ENCODING 117 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR 0076 +ENCODING 118 +SWIDTH 400 0 +DWIDTH 5 0 +BBX 5 7 0 0 +BITMAP +88 +88 +50 +50 +50 +20 +20 +ENDCHAR +STARTCHAR 0077 +ENCODING 119 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 9 7 0 0 +BITMAP +8880 +8C80 +5500 +5500 +5500 +2200 +2200 +ENDCHAR +STARTCHAR 0078 +ENCODING 120 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +88 +50 +50 +20 +50 +50 +88 +ENDCHAR +STARTCHAR 0079 +ENCODING 121 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +88 +88 +50 +50 +50 +20 +20 +20 +20 +C0 +ENDCHAR +STARTCHAR 007A +ENCODING 122 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +F8 +10 +10 +20 +40 +40 +F8 +ENDCHAR +STARTCHAR 007B +ENCODING 123 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 3 13 0 -3 +BITMAP +20 +40 +40 +40 +40 +40 +80 +40 +40 +40 +40 +40 +20 +ENDCHAR +STARTCHAR 007C +ENCODING 124 +SWIDTH 240 0 +DWIDTH 3 0 +BBX 1 12 1 -2 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR 007D +ENCODING 125 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 3 13 1 -3 +BITMAP +80 +40 +40 +40 +40 +40 +20 +40 +40 +40 +40 +40 +80 +ENDCHAR +STARTCHAR 007E +ENCODING 126 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 7 2 0 4 +BITMAP +72 +9C +ENDCHAR +STARTCHAR 00A0 +ENCODING 160 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +ENDFONT diff --git a/gui/themes/fonts/Arial12.bdf b/gui/themes/fonts/Arial12.bdf new file mode 100644 index 0000000000..ddca587007 --- /dev/null +++ b/gui/themes/fonts/Arial12.bdf @@ -0,0 +1,7119 @@ +STARTFONT 2.1 +COMMENT +COMMENT Converted from TrueType font "arialbd.ttf" by "ttf2bdf 2.8". +COMMENT +FONT -FreeType-Arial-Bold-R-Normal--104-750-100-100-P-481-ISO10646-1 +SIZE 75 100 100 +FONTBOUNDINGBOX 105 104 -5 -24 +STARTPROPERTIES 19 +FOUNDRY "FreeType" +FAMILY_NAME "Arial" +WEIGHT_NAME "Bold" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 104 +POINT_SIZE 750 +RESOLUTION_X 100 +RESOLUTION_Y 100 +SPACING "P" +AVERAGE_WIDTH 481 +CHARSET_REGISTRY "ISO10646" +CHARSET_ENCODING "1" +FONT_ASCENT 94 +FONT_DESCENT 22 +COPYRIGHT "Typeface © The Monotype Corporation plc. Data © The Monotype Corporation plc/Type Solutions Inc. 1990-1992. All Rights Reserved" +_TTF_FONTFILE "arialbd.ttf" +_TTF_PSNAME "Arial-BoldMT" +ENDPROPERTIES +CHARS 96 +STARTCHAR 0020 +ENCODING 32 +SWIDTH 268 0 +DWIDTH 28 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR 0021 +ENCODING 33 +SWIDTH 307 0 +DWIDTH 32 0 +BBX 14 75 9 0 +BITMAP +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +7FFC +7FF8 +7FF8 +7FF8 +7FF8 +7FF8 +7FF8 +7FF8 +7FF8 +7FF8 +7FF8 +3FF8 +3FF8 +3FF0 +3FF0 +3FF0 +3FF0 +3FF0 +3FF0 +3FF0 +3FF0 +3FF0 +3FF0 +1FF0 +1FE0 +1FE0 +1FE0 +1FE0 +1FE0 +1FE0 +1FE0 +1FE0 +1FE0 +0000 +0000 +0000 +0000 +0000 +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +ENDCHAR +STARTCHAR 0022 +ENCODING 34 +SWIDTH 470 0 +DWIDTH 49 0 +BBX 38 27 5 48 +BITMAP +FFFC00FFFC +FFFC00FFFC +FFFC00FFFC +FFFC00FFFC +FFFC00FFFC +FFFC00FFFC +FFFC00FFFC +FFFC00FFFC +FFFC00FFFC +FFFC00FFFC +FFFC00FFFC +FFFC00FFFC +FFFC00FFFC +FFFC00FFFC +FFFC00FFFC +FFFC00FFFC +7FF8007FF8 +7FF8007FF8 +7FF8007FF8 +7FF8007FF8 +7FF8007FF8 +7FF8007FF8 +3FF8003FF8 +3FF0003FF0 +3FF0003FF0 +3FF0003FF0 +3FF0003FF0 +ENDCHAR +STARTCHAR 0023 +ENCODING 35 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 56 75 1 0 +BITMAP +00001FFC003FF8 +00001FFC003FF8 +00003FFC007FF8 +00003FFC007FF8 +00003FF8007FF0 +00003FF8007FF0 +00003FF8007FF0 +00007FF800FFF0 +00007FF000FFE0 +00007FF000FFE0 +00007FF000FFE0 +00007FF000FFE0 +0000FFF001FFE0 +0000FFE001FFC0 +0000FFE001FFC0 +0000FFE001FFC0 +0001FFE003FFC0 +0001FFE003FFC0 +0001FFC003FF80 +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +000FFF001FFE00 +000FFF001FFE00 +000FFE001FFC00 +000FFE001FFC00 +000FFE001FFC00 +001FFE003FFC00 +001FFC003FF800 +001FFC003FF800 +001FFC003FF800 +001FFC003FF800 +003FFC007FF800 +003FF8007FF000 +003FF8007FF000 +003FF8007FF000 +007FF800FFF000 +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +01FFC003FF8000 +01FFC003FF8000 +01FFC003FF8000 +03FFC007FF8000 +03FF8007FF0000 +03FF8007FF0000 +03FF8007FF0000 +07FF800FFF0000 +07FF000FFE0000 +07FF000FFE0000 +07FF000FFE0000 +07FF000FFE0000 +0FFF001FFE0000 +0FFE001FFC0000 +0FFE001FFC0000 +0FFE001FFC0000 +0FFE001FFC0000 +1FFE003FFC0000 +1FFC003FF80000 +ENDCHAR +STARTCHAR 0024 +ENCODING 36 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 50 90 3 -10 +BITMAP +000007F0000000 +000007F0000000 +000007F0000000 +000007F0000000 +000007F0000000 +00003FFE000000 +0001FFFFE00000 +000FFFFFF80000 +001FFFFFFE0000 +007FFFFFFF0000 +00FFFFFFFFC000 +01FFFFFFFFE000 +03FFFFFFFFF000 +07FFFFFFFFF000 +07FFFFFFFFF800 +0FFFFFFFFFFC00 +0FFFF7F7FFFC00 +1FFFC7F1FFFE00 +1FFF87F0FFFE00 +1FFF07F07FFE00 +3FFF07F07FFF00 +3FFE07F03FFF00 +3FFE07F03FF800 +3FFE07F01C0000 +3FFE07F0000000 +3FFE07F0000000 +3FFE07F0000000 +3FFE07F0000000 +3FFF07F0000000 +3FFF07F0000000 +1FFF87F0000000 +1FFFC7F0000000 +1FFFF7F0000000 +1FFFFFF0000000 +0FFFFFF0000000 +0FFFFFF0000000 +07FFFFFF000000 +03FFFFFFE00000 +03FFFFFFF80000 +01FFFFFFFE0000 +00FFFFFFFF8000 +007FFFFFFFE000 +001FFFFFFFF000 +000FFFFFFFF800 +0003FFFFFFFC00 +0000FFFFFFFE00 +00001FFFFFFE00 +000007FFFFFF00 +000007FFFFFF00 +000007F7FFFF80 +000007F1FFFF80 +000007F07FFF80 +000007F03FFFC0 +000007F01FFFC0 +000007F00FFFC0 +000007F00FFFC0 +000007F007FFC0 +003807F007FFC0 +1FF807F007FFC0 +FFFC07F007FFC0 +FFFC07F007FFC0 +FFFE07F007FFC0 +7FFE07F00FFF80 +7FFF07F00FFF80 +7FFF87F01FFF80 +3FFF87F03FFF80 +3FFFE7F07FFF00 +3FFFF7F1FFFF00 +1FFFFFFFFFFE00 +1FFFFFFFFFFE00 +0FFFFFFFFFFC00 +07FFFFFFFFF800 +07FFFFFFFFF800 +03FFFFFFFFF000 +01FFFFFFFFE000 +00FFFFFFFF8000 +007FFFFFFF0000 +001FFFFFFC0000 +0007FFFFF00000 +0001FFFFC00000 +00003FFC000000 +000007F0000000 +000007F0000000 +000007F0000000 +000007F0000000 +000007F0000000 +000007F0000000 +000007F0000000 +000007F0000000 +000007F0000000 +ENDCHAR +STARTCHAR 0025 +ENCODING 37 +SWIDTH 864 0 +DWIDTH 90 0 +BBX 81 79 4 -3 +BITMAP +000FF000000001FFC00000 +007FFE00000003FF800000 +01FFFF80000003FF800000 +03FFFFC0000007FF000000 +07FFFFE0000007FF000000 +0FFFFFF000000FFE000000 +1FFFFFF800000FFE000000 +3FFFFFFC00001FFC000000 +3FFC3FFC00001FFC000000 +7FF81FFC00003FF8000000 +7FF00FFE00003FF8000000 +7FF00FFE00007FF0000000 +7FF00FFE00007FF0000000 +FFE007FE0000FFE0000000 +FFE007FF0000FFE0000000 +FFE007FF0001FFC0000000 +FFE007FF0001FFC0000000 +FFE007FF0003FF80000000 +FFE007FF0003FF80000000 +FFE007FF0007FF00000000 +FFE007FF0007FF00000000 +FFE007FF000FFE00000000 +FFE007FF000FFE00000000 +FFE007FF001FFC00000000 +FFE007FF001FFC00000000 +FFE007FE003FFC00000000 +7FF00FFE003FF800000000 +7FF00FFE007FF800000000 +7FF00FFE007FF000000000 +7FF81FFC007FF000000000 +3FFC3FFC00FFE000000000 +3FFFFFFC00FFE000000000 +1FFFFFF801FFC000000000 +0FFFFFF001FFC000000000 +0FFFFFE003FF8000000000 +03FFFFC003FF8000000000 +01FFFF8007FF0000000000 +007FFE0007FF0000000000 +000FF0000FFE0000000000 +000000000FFE0000000000 +000000001FFC0007F80000 +000000001FFC003FFF0000 +000000003FF800FFFFC000 +000000003FF801FFFFE000 +000000007FF003FFFFF000 +000000007FF007FFFFF800 +00000000FFE00FFFFFFC00 +00000000FFE01FFFFFFE00 +00000001FFC01FFE1FFE00 +00000001FFC03FFC0FFE00 +00000003FF803FF807FF00 +00000003FF803FF807FF00 +00000007FF003FF807FF00 +00000007FF007FF003FF00 +0000000FFE007FF003FF80 +0000000FFE007FF003FF80 +0000001FFC007FF003FF80 +0000001FFC007FF003FF80 +0000003FF8007FF003FF80 +0000003FF8007FF003FF80 +0000007FF0007FF003FF80 +0000007FF0007FF003FF80 +000000FFE0007FF003FF80 +000000FFE0007FF003FF80 +000001FFC0007FF003FF80 +000001FFC0007FF003FF00 +000003FF80003FF807FF00 +000003FF80003FF807FF00 +000007FF00003FF807FF00 +000007FF00003FFC0FFE00 +00000FFE00001FFE1FFE00 +00000FFE00001FFFFFFE00 +00001FFE00000FFFFFFC00 +00001FFC000007FFFFF800 +00003FFC000003FFFFF000 +00003FF8000001FFFFE000 +00003FF8000000FFFFC000 +00007FF00000003FFF0000 +00007FF000000007F80000 +ENDCHAR +STARTCHAR 0026 +ENCODING 38 +SWIDTH 720 0 +DWIDTH 75 0 +BBX 69 77 4 -1 +BITMAP +000001FFE000000000 +00001FFFFE00000000 +00007FFFFFC0000000 +0001FFFFFFE0000000 +0003FFFFFFF8000000 +0007FFFFFFFC000000 +000FFFFFFFFE000000 +001FFFFFFFFF000000 +003FFFFFFFFF800000 +003FFFFFFFFF800000 +007FFFC07FFFC00000 +007FFF003FFFC00000 +00FFFE001FFFC00000 +00FFFC000FFFE00000 +00FFFC0007FFE00000 +00FFFC0007FFE00000 +00FFFC0007FFE00000 +00FFFC0007FFE00000 +00FFFE0007FFE00000 +00FFFE000FFFE00000 +007FFF001FFFC00000 +007FFF803FFFC00000 +003FFFC07FFFC00000 +003FFFE0FFFF800000 +001FFFF3FFFF000000 +001FFFFFFFFF000000 +000FFFFFFFFE000000 +0007FFFFFFFC000000 +0007FFFFFFF8000000 +0003FFFFFFE0000000 +0001FFFFFFC0000000 +0000FFFFFF00000000 +0001FFFFFE00000000 +0003FFFFF800000000 +000FFFFFF800000000 +001FFFFFFC00000000 +007FFFFFFC00000000 +00FFFFFFFE00000000 +01FFFFFFFF00000000 +03FFFFFFFF80100000 +07FFFFFFFFC01F0000 +0FFFFCFFFFC03FF800 +0FFFF07FFFE03FFF00 +1FFFE03FFFF07FFE00 +1FFFC03FFFF87FFE00 +3FFF801FFFFC7FFE00 +3FFF000FFFFEFFFC00 +7FFF0007FFFFFFFC00 +7FFE0003FFFFFFFC00 +7FFE0001FFFFFFF800 +FFFC0001FFFFFFF800 +FFFC0000FFFFFFF800 +FFFC00007FFFFFF000 +FFFC00003FFFFFF000 +FFFC00001FFFFFE000 +FFFC00000FFFFFE000 +FFFC00000FFFFFC000 +FFFE000007FFFFC000 +FFFE000003FFFFE000 +FFFF000007FFFFF000 +7FFF00001FFFFFF800 +7FFF80003FFFFFFE00 +7FFFE000FFFFFFFF00 +3FFFF807FFFFFFFFC0 +3FFFFFFFFFFFFFFFE0 +1FFFFFFFFFFFFFFFF8 +1FFFFFFFFFFFFFFFF0 +0FFFFFFFFFFFFFFFF0 +07FFFFFFFFFFFFFFE0 +03FFFFFFFFFE7FFFC0 +01FFFFFFFFFC1FFF80 +00FFFFFFFFF00FFF80 +007FFFFFFFE007FF00 +001FFFFFFF8003FE00 +0007FFFFFE0000FC00 +0001FFFFF800003C00 +00000FFF8000001800 +ENDCHAR +STARTCHAR 0027 +ENCODING 39 +SWIDTH 240 0 +DWIDTH 25 0 +BBX 14 27 5 48 +BITMAP +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +7FF8 +7FF8 +7FF8 +7FF8 +7FF8 +7FF8 +3FF8 +3FF0 +3FF0 +3FF0 +3FF0 +ENDCHAR +STARTCHAR 0028 +ENCODING 40 +SWIDTH 336 0 +DWIDTH 35 0 +BBX 25 96 5 -21 +BITMAP +0000FF80 +0001FF00 +0003FF00 +0003FF00 +0007FE00 +000FFE00 +000FFC00 +001FFC00 +001FFC00 +003FF800 +003FF800 +007FF800 +007FF000 +00FFF000 +00FFF000 +01FFE000 +01FFE000 +03FFE000 +03FFC000 +07FFC000 +07FFC000 +07FF8000 +0FFF8000 +0FFF8000 +0FFF8000 +1FFF0000 +1FFF0000 +1FFF0000 +3FFF0000 +3FFF0000 +3FFE0000 +3FFE0000 +3FFE0000 +7FFE0000 +7FFE0000 +7FFE0000 +7FFE0000 +7FFC0000 +7FFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +7FFC0000 +7FFC0000 +7FFE0000 +7FFE0000 +7FFE0000 +7FFE0000 +7FFE0000 +3FFE0000 +3FFE0000 +3FFE0000 +3FFF0000 +1FFF0000 +1FFF0000 +1FFF0000 +0FFF0000 +0FFF8000 +0FFF8000 +07FF8000 +07FF8000 +07FFC000 +03FFC000 +03FFC000 +03FFC000 +01FFE000 +01FFE000 +00FFE000 +00FFF000 +007FF000 +007FF000 +003FF800 +003FF800 +001FF800 +001FFC00 +000FFC00 +000FFE00 +0007FE00 +0003FE00 +0003FF00 +0001FF00 +0000FF80 +ENDCHAR +STARTCHAR 0029 +ENCODING 41 +SWIDTH 336 0 +DWIDTH 35 0 +BBX 25 96 5 -21 +BITMAP +FF800000 +7FC00000 +7FE00000 +7FE00000 +3FF00000 +3FF80000 +1FF80000 +1FFC0000 +1FFC0000 +0FFE0000 +0FFE0000 +0FFF0000 +07FF0000 +07FF8000 +07FF8000 +03FFC000 +03FFC000 +03FFE000 +01FFE000 +01FFF000 +01FFF000 +00FFF000 +00FFF800 +00FFF800 +00FFF800 +007FFC00 +007FFC00 +007FFC00 +007FFE00 +007FFE00 +003FFE00 +003FFE00 +003FFE00 +003FFF00 +003FFF00 +003FFF00 +003FFF00 +003FFF00 +001FFF00 +001FFF80 +001FFF80 +001FFF80 +001FFF80 +001FFF80 +001FFF80 +001FFF80 +001FFF80 +001FFF80 +001FFF80 +001FFF80 +001FFF80 +001FFF80 +001FFF80 +001FFF80 +001FFF80 +001FFF00 +001FFF00 +001FFF00 +003FFF00 +003FFF00 +003FFF00 +003FFF00 +003FFE00 +003FFE00 +003FFE00 +007FFE00 +007FFC00 +007FFC00 +007FFC00 +007FFC00 +007FF800 +00FFF800 +00FFF800 +00FFF000 +00FFF000 +01FFF000 +01FFE000 +01FFE000 +01FFC000 +03FFC000 +03FFC000 +03FF8000 +07FF8000 +07FF0000 +07FF0000 +0FFE0000 +0FFE0000 +0FFC0000 +1FFC0000 +1FF80000 +3FF00000 +3FF00000 +7FE00000 +7FE00000 +7FC00000 +FF800000 +ENDCHAR +STARTCHAR 002A +ENCODING 42 +SWIDTH 384 0 +DWIDTH 40 0 +BBX 37 35 1 40 +BITMAP +0003FE0000 +0003FE0000 +0003FE0000 +0003FE0000 +0003FE0000 +0003FE0000 +0003FE0000 +0003FC0000 +1801FC00C0 +1E01FC03C0 +1F81FC0FC0 +3FE1FC3FE0 +3FF9FCFFE0 +7FFFFFFFF0 +7FFFFFFFF0 +7FFFFFFFF0 +FFFFFFFFF8 +3FFFFFFFE0 +00FFFFFC00 +0007FF0000 +000FFF8000 +001FFFC000 +003FFFE000 +007FFFF000 +00FFDFF800 +01FF8FFC00 +03FF07FE00 +07FF07FF00 +0FFE03FF80 +1FFC01FFC0 +0FFC01FF80 +03F800FE00 +01F0007C00 +00F0007800 +0020002000 +ENDCHAR +STARTCHAR 002B +ENCODING 43 +SWIDTH 585 0 +DWIDTH 61 0 +BBX 51 51 4 11 +BITMAP +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +00001FFF000000 +ENDCHAR +STARTCHAR 002C +ENCODING 44 +SWIDTH 278 0 +DWIDTH 29 0 +BBX 15 31 6 -17 +BITMAP +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +00FE +00FE +00FE +00FE +01FC +01FC +03FC +03F8 +07F8 +1FF0 +7FF0 +FFE0 +7FC0 +7F80 +3F00 +3C00 +1000 +ENDCHAR +STARTCHAR 002D +ENCODING 45 +SWIDTH 336 0 +DWIDTH 35 0 +BBX 29 13 5 20 +BITMAP +FFFFFFF8 +FFFFFFF8 +FFFFFFF8 +FFFFFFF8 +FFFFFFF8 +FFFFFFF8 +FFFFFFF8 +FFFFFFF8 +FFFFFFF8 +FFFFFFF8 +FFFFFFF8 +FFFFFFF8 +FFFFFFF8 +ENDCHAR +STARTCHAR 002E +ENCODING 46 +SWIDTH 278 0 +DWIDTH 29 0 +BBX 14 14 7 0 +BITMAP +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +ENDCHAR +STARTCHAR 002F +ENCODING 47 +SWIDTH 278 0 +DWIDTH 29 0 +BBX 29 75 0 0 +BITMAP +00003FF8 +00007FF8 +00007FF0 +00007FF0 +00007FF0 +0000FFF0 +0000FFE0 +0000FFE0 +0000FFE0 +0001FFE0 +0001FFE0 +0001FFC0 +0001FFC0 +0003FFC0 +0003FFC0 +0003FF80 +0003FF80 +0007FF80 +0007FF80 +0007FF00 +0007FF00 +0007FF00 +000FFF00 +000FFE00 +000FFE00 +000FFE00 +001FFE00 +001FFC00 +001FFC00 +001FFC00 +003FFC00 +003FF800 +003FF800 +003FF800 +007FF800 +007FF800 +007FF000 +007FF000 +00FFF000 +00FFF000 +00FFE000 +00FFE000 +01FFE000 +01FFE000 +01FFC000 +01FFC000 +01FFC000 +03FFC000 +03FF8000 +03FF8000 +03FF8000 +07FF8000 +07FF0000 +07FF0000 +07FF0000 +0FFF0000 +0FFE0000 +0FFE0000 +0FFE0000 +1FFE0000 +1FFE0000 +1FFC0000 +1FFC0000 +3FFC0000 +3FFC0000 +3FF80000 +3FF80000 +7FF80000 +7FF80000 +7FF00000 +7FF00000 +7FF00000 +FFF00000 +FFE00000 +FFE00000 +ENDCHAR +STARTCHAR 0030 +ENCODING 48 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 49 76 4 -1 +BITMAP +00001FFC000000 +0000FFFF800000 +0003FFFFE00000 +000FFFFFF80000 +003FFFFFFC0000 +007FFFFFFF0000 +00FFFFFFFF8000 +01FFFFFFFF8000 +01FFFFFFFFC000 +03FFFFFFFFE000 +07FFFFFFFFE000 +07FFFFFFFFF000 +0FFFFFFFFFF800 +0FFFF80FFFF800 +1FFFE003FFF800 +1FFFC001FFFC00 +1FFF8000FFFC00 +3FFF8000FFFC00 +3FFF00007FFE00 +3FFF00007FFE00 +3FFF00007FFE00 +7FFE00003FFE00 +7FFE00003FFF00 +7FFE00003FFF00 +7FFE00003FFF00 +7FFE00003FFF00 +7FFC00001FFF00 +7FFC00001FFF00 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF00 +7FFC00003FFF00 +7FFE00003FFF00 +7FFE00003FFF00 +7FFE00003FFF00 +7FFE00003FFF00 +7FFE00003FFF00 +3FFF00007FFE00 +3FFF00007FFE00 +3FFF00007FFE00 +3FFF8000FFFC00 +1FFF8000FFFC00 +1FFFC001FFFC00 +1FFFE003FFF800 +0FFFF80FFFF800 +0FFFFFFFFFF800 +07FFFFFFFFF000 +07FFFFFFFFF000 +03FFFFFFFFE000 +01FFFFFFFFC000 +01FFFFFFFFC000 +00FFFFFFFF8000 +007FFFFFFF0000 +001FFFFFFE0000 +000FFFFFF80000 +0003FFFFE00000 +0000FFFF800000 +00001FFC000000 +ENDCHAR +STARTCHAR 0031 +ENCODING 49 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 32 75 8 0 +BITMAP +00000FFF +00000FFF +00000FFF +00001FFF +00001FFF +00003FFF +00007FFF +0000FFFF +0000FFFF +0001FFFF +0003FFFF +000FFFFF +001FFFFF +003FFFFF +007FFFFF +01FFFFFF +07FFFFFF +0FFFFFFF +7FFFFFFF +FFFFFFFF +FFFFFFFF +FFFFFFFF +FFFFBFFF +FFFF3FFF +FFFE3FFF +FFF83FFF +FFF03FFF +FFE03FFF +FF803FFF +FF003FFF +FC003FFF +F0003FFF +80003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +00003FFF +ENDCHAR +STARTCHAR 0032 +ENCODING 50 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 49 75 4 0 +BITMAP +000007FF000000 +00007FFFF00000 +0003FFFFFC0000 +000FFFFFFF0000 +001FFFFFFF8000 +007FFFFFFFC000 +00FFFFFFFFE000 +01FFFFFFFFF000 +01FFFFFFFFF800 +03FFFFFFFFFC00 +07FFFFFFFFFC00 +07FFFFFFFFFE00 +0FFFFFFFFFFE00 +0FFFFC07FFFF00 +0FFFF001FFFF00 +1FFFE000FFFF00 +1FFFC0007FFF80 +1FFFC0003FFF80 +1FFF80003FFF80 +3FFF80001FFF80 +3FFF00001FFF80 +3FFF00001FFF80 +3FFF00001FFF80 +001F00001FFF80 +000000001FFF80 +000000001FFF80 +000000003FFF00 +000000003FFF00 +000000003FFF00 +000000007FFE00 +000000007FFE00 +00000000FFFE00 +00000001FFFC00 +00000003FFFC00 +00000007FFF800 +00000007FFF800 +0000000FFFF000 +0000001FFFE000 +0000003FFFC000 +0000007FFFC000 +000000FFFF8000 +000001FFFF0000 +000007FFFE0000 +00000FFFFC0000 +00001FFFF80000 +00003FFFF00000 +00007FFFE00000 +0000FFFFC00000 +0001FFFF800000 +0003FFFF000000 +0007FFFE000000 +000FFFFC000000 +001FFFF8000000 +003FFFF0000000 +003FFFE0000000 +007FFF80000000 +00FFFF80000000 +01FFFF00000000 +03FFFE00000000 +03FFFC00000000 +07FFF800000000 +0FFFFFFFFFFF80 +0FFFFFFFFFFF80 +1FFFFFFFFFFF80 +1FFFFFFFFFFF80 +3FFFFFFFFFFF80 +3FFFFFFFFFFF80 +3FFFFFFFFFFF80 +7FFFFFFFFFFF80 +7FFFFFFFFFFF80 +7FFFFFFFFFFF80 +7FFFFFFFFFFF80 +FFFFFFFFFFFF80 +FFFFFFFFFFFF80 +FFFFFFFFFFFF80 +ENDCHAR +STARTCHAR 0033 +ENCODING 51 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 49 76 4 -1 +BITMAP +00001FFC000000 +0000FFFF800000 +0007FFFFE00000 +000FFFFFF80000 +003FFFFFFE0000 +007FFFFFFF0000 +00FFFFFFFF8000 +01FFFFFFFFC000 +03FFFFFFFFC000 +03FFFFFFFFE000 +07FFFFFFFFF000 +07FFFFFFFFF000 +0FFFFFFFFFF800 +0FFFFC0FFFF800 +1FFFF007FFF800 +1FFFE003FFFC00 +1FFFC001FFFC00 +1FFF8000FFFC00 +3FFF8000FFFC00 +3FFF0000FFFC00 +03FF0000FFFC00 +00070000FFFC00 +00000000FFFC00 +00000001FFF800 +00000001FFF800 +00000003FFF800 +00000003FFF000 +0000000FFFE000 +0000003FFFE000 +000007FFFFC000 +000007FFFF8000 +000007FFFF0000 +000007FFFE0000 +000007FFF80000 +000007FFF00000 +000007FFFE0000 +000007FFFF8000 +00000FFFFFC000 +00000FFFFFE000 +00000FFFFFF000 +00000C07FFF800 +00000001FFFC00 +00000000FFFE00 +000000007FFE00 +000000007FFF00 +000000003FFF00 +000000003FFF00 +000000001FFF00 +000000001FFF80 +000000001FFF80 +000000001FFF80 +000000001FFF80 +003C00001FFF80 +3FFC00001FFF80 +FFFC00001FFF80 +FFFE00003FFF80 +FFFE00003FFF80 +7FFF00003FFF00 +7FFF00007FFF00 +7FFF8000FFFF00 +7FFFC001FFFF00 +3FFFE003FFFE00 +3FFFF80FFFFE00 +1FFFFFFFFFFC00 +1FFFFFFFFFFC00 +0FFFFFFFFFF800 +07FFFFFFFFF000 +07FFFFFFFFE000 +03FFFFFFFFC000 +01FFFFFFFF8000 +00FFFFFFFF0000 +003FFFFFFE0000 +001FFFFFFC0000 +0007FFFFF00000 +0001FFFF800000 +00001FFC000000 +ENDCHAR +STARTCHAR 0034 +ENCODING 52 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 54 74 2 0 +BITMAP +00000000FFF800 +00000000FFF800 +00000001FFF800 +00000003FFF800 +00000003FFF800 +00000007FFF800 +0000000FFFF800 +0000001FFFF800 +0000001FFFF800 +0000003FFFF800 +0000007FFFF800 +0000007FFFF800 +000000FFFFF800 +000001FFFFF800 +000003FFFFF800 +000003FFFFF800 +000007FFFFF800 +00000FFFFFF800 +00000FFFFFF800 +00001FFFFFF800 +00003FFFFFF800 +00007FFFFFF800 +00007FFDFFF800 +0000FFF9FFF800 +0001FFF9FFF800 +0001FFF1FFF800 +0003FFE1FFF800 +0007FFE1FFF800 +0007FFC1FFF800 +000FFF81FFF800 +001FFF01FFF800 +003FFF01FFF800 +003FFE01FFF800 +007FFC01FFF800 +00FFFC01FFF800 +00FFF801FFF800 +01FFF001FFF800 +03FFE001FFF800 +07FFE001FFF800 +07FFC001FFF800 +0FFF8001FFF800 +1FFF8001FFF800 +1FFF0001FFF800 +3FFE0001FFF800 +7FFC0001FFF800 +FFFC0001FFF800 +FFFFFFFFFFFFFC +FFFFFFFFFFFFFC +FFFFFFFFFFFFFC +FFFFFFFFFFFFFC +FFFFFFFFFFFFFC +FFFFFFFFFFFFFC +FFFFFFFFFFFFFC +FFFFFFFFFFFFFC +FFFFFFFFFFFFFC +FFFFFFFFFFFFFC +FFFFFFFFFFFFFC +FFFFFFFFFFFFFC +FFFFFFFFFFFFFC +00000001FFF800 +00000001FFF800 +00000001FFF800 +00000001FFF800 +00000001FFF800 +00000001FFF800 +00000001FFF800 +00000001FFF800 +00000001FFF800 +00000001FFF800 +00000001FFF800 +00000001FFF800 +00000001FFF800 +00000001FFF800 +00000001FFF800 +ENDCHAR +STARTCHAR 0035 +ENCODING 53 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 50 75 4 -1 +BITMAP +003FFFFFFFFE00 +003FFFFFFFFE00 +007FFFFFFFFE00 +007FFFFFFFFE00 +007FFFFFFFFE00 +007FFFFFFFFE00 +007FFFFFFFFE00 +007FFFFFFFFE00 +00FFFFFFFFFE00 +00FFFFFFFFFE00 +00FFFFFFFFFE00 +00FFFFFFFFFE00 +00FFFFFFFFFE00 +01FFFFFFFFFE00 +01FFF800000000 +01FFF800000000 +01FFF800000000 +01FFF800000000 +03FFF800000000 +03FFF000000000 +03FFF000000000 +03FFF000000000 +03FFF000000000 +07FFF000000000 +07FFE0FF800000 +07FFE7FFF00000 +07FFFFFFFC0000 +07FFFFFFFF0000 +0FFFFFFFFF8000 +0FFFFFFFFFC000 +0FFFFFFFFFE000 +0FFFFFFFFFF000 +0FFFFFFFFFF800 +1FFFFFFFFFFC00 +1FFFFFFFFFFC00 +1FFFFFFFFFFE00 +1FFFFFFFFFFE00 +1FFFF807FFFF00 +3FFFE001FFFF00 +3FFF8000FFFF80 +3FFF00007FFF80 +003E00003FFF80 +000000001FFF80 +000000001FFFC0 +000000001FFFC0 +000000000FFFC0 +000000000FFFC0 +000000000FFFC0 +000000000FFFC0 +000000000FFFC0 +000000000FFFC0 +007800000FFFC0 +7FF800000FFFC0 +FFFC00000FFFC0 +FFFC00001FFF80 +FFFC00001FFF80 +7FFE00003FFF80 +7FFE00003FFF80 +7FFF00007FFF00 +3FFF8000FFFF00 +3FFFE003FFFE00 +3FFFF80FFFFE00 +1FFFFFFFFFFC00 +1FFFFFFFFFFC00 +0FFFFFFFFFF800 +07FFFFFFFFF000 +07FFFFFFFFF000 +03FFFFFFFFE000 +01FFFFFFFFC000 +00FFFFFFFF8000 +003FFFFFFE0000 +001FFFFFFC0000 +0007FFFFF00000 +0001FFFFC00000 +00001FFC000000 +ENDCHAR +STARTCHAR 0036 +ENCODING 54 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 49 76 4 -1 +BITMAP +000007FE000000 +00003FFFE00000 +0001FFFFF80000 +0003FFFFFC0000 +000FFFFFFE0000 +001FFFFFFF8000 +003FFFFFFFC000 +007FFFFFFFC000 +00FFFFFFFFE000 +01FFFFFFFFF000 +03FFFFFFFFF000 +03FFFFFFFFF800 +07FFFFFFFFF800 +0FFFFC0FFFF800 +0FFFF003FFFC00 +0FFFC001FFFC00 +1FFF8000FFFC00 +1FFF8000FFFE00 +3FFF0000FFFE00 +3FFF00007FFE00 +3FFE00007C0000 +3FFE0000000000 +7FFE0000000000 +7FFC0000000000 +7FFC0000000000 +7FFC0000000000 +7FFC0000000000 +7FFC0000000000 +FFF803FE000000 +FFF81FFFE00000 +FFF87FFFF80000 +FFF8FFFFFE0000 +FFF9FFFFFF0000 +FFFBFFFFFF8000 +FFFFFFFFFFC000 +FFFFFFFFFFE000 +FFFFFFFFFFF000 +FFFFFFFFFFF800 +FFFFFFFFFFF800 +FFFFFFFFFFFC00 +FFFFFFFFFFFE00 +FFFFF80FFFFE00 +FFFFE003FFFE00 +FFFF8000FFFF00 +FFFF00007FFF00 +FFFE00007FFF00 +FFFE00003FFF80 +FFFE00003FFF80 +7FFC00001FFF80 +7FFC00001FFF80 +7FFC00001FFF80 +7FFC00001FFF80 +7FFC00001FFF80 +7FFC00001FFF80 +7FFC00001FFF80 +3FFE00001FFF80 +3FFE00003FFF80 +3FFE00003FFF00 +1FFF00003FFF00 +1FFF80007FFF00 +1FFFC000FFFF00 +0FFFE001FFFE00 +0FFFFC07FFFE00 +07FFFFFFFFFE00 +07FFFFFFFFFC00 +03FFFFFFFFF800 +01FFFFFFFFF800 +01FFFFFFFFF000 +00FFFFFFFFE000 +007FFFFFFFC000 +003FFFFFFF8000 +001FFFFFFF0000 +0007FFFFFC0000 +0001FFFFF80000 +00007FFFC00000 +00000FFE000000 +ENDCHAR +STARTCHAR 0037 +ENCODING 55 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 49 74 4 0 +BITMAP +FFFFFFFFFFFF80 +FFFFFFFFFFFF80 +FFFFFFFFFFFF80 +FFFFFFFFFFFF80 +FFFFFFFFFFFF80 +FFFFFFFFFFFF80 +FFFFFFFFFFFF80 +FFFFFFFFFFFF80 +FFFFFFFFFFFF80 +FFFFFFFFFFFF80 +FFFFFFFFFFFF80 +FFFFFFFFFFFF80 +FFFFFFFFFFFF00 +FFFFFFFFFFFE00 +00000000FFFC00 +00000001FFF800 +00000001FFF000 +00000003FFE000 +00000007FFE000 +00000007FFC000 +0000000FFF8000 +0000001FFF8000 +0000001FFF0000 +0000003FFE0000 +0000007FFE0000 +0000007FFC0000 +000000FFFC0000 +000001FFF80000 +000001FFF00000 +000003FFF00000 +000003FFE00000 +000007FFE00000 +000007FFC00000 +00000FFFC00000 +00000FFF800000 +00001FFF800000 +00001FFF800000 +00003FFF000000 +00003FFF000000 +00003FFE000000 +00007FFE000000 +00007FFC000000 +0000FFFC000000 +0000FFFC000000 +0000FFF8000000 +0001FFF8000000 +0001FFF8000000 +0001FFF0000000 +0003FFF0000000 +0003FFF0000000 +0003FFF0000000 +0007FFE0000000 +0007FFE0000000 +0007FFE0000000 +0007FFE0000000 +000FFFC0000000 +000FFFC0000000 +000FFFC0000000 +000FFFC0000000 +000FFF80000000 +001FFF80000000 +001FFF80000000 +001FFF80000000 +001FFF80000000 +001FFF80000000 +001FFF00000000 +003FFF00000000 +003FFF00000000 +003FFF00000000 +003FFF00000000 +003FFF00000000 +003FFF00000000 +003FFF00000000 +003FFF00000000 +ENDCHAR +STARTCHAR 0038 +ENCODING 56 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 49 76 4 -1 +BITMAP +00001FFC000000 +0003FFFFC00000 +000FFFFFF80000 +003FFFFFFE0000 +007FFFFFFF0000 +00FFFFFFFF8000 +01FFFFFFFFC000 +03FFFFFFFFE000 +07FFFFFFFFF000 +0FFFFFFFFFF000 +0FFFFFFFFFF800 +1FFFFC0FFFFC00 +1FFFE003FFFC00 +1FFFC001FFFC00 +3FFF8000FFFE00 +3FFF8000FFFE00 +3FFF80007FFE00 +3FFF00007FFE00 +3FFF00007FFE00 +3FFF00007FFE00 +3FFF00007FFE00 +3FFF00007FFE00 +3FFF00007FFE00 +1FFF0000FFFC00 +1FFF8000FFFC00 +1FFF8000FFFC00 +0FFFC001FFF800 +0FFFE003FFF800 +07FFF80FFFF000 +03FFFFFFFFE000 +01FFFFFFFFC000 +00FFFFFFFF8000 +007FFFFFFF0000 +001FFFFFFC0000 +000FFFFFF80000 +003FFFFFFE0000 +00FFFFFFFF8000 +01FFFFFFFFC000 +03FFFFFFFFE000 +07FFFFFFFFF000 +0FFFF80FFFF800 +1FFFE003FFFC00 +1FFFC001FFFC00 +3FFF8000FFFE00 +3FFF00007FFE00 +7FFF00003FFF00 +7FFE00003FFF00 +7FFE00003FFF00 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFC00001FFF80 +FFFE00003FFF80 +7FFE00003FFF00 +7FFF00003FFF00 +7FFF00007FFF00 +7FFF8000FFFF00 +3FFFC001FFFE00 +3FFFE003FFFE00 +1FFFF80FFFFC00 +1FFFFFFFFFFC00 +0FFFFFFFFFF800 +07FFFFFFFFF000 +03FFFFFFFFE000 +01FFFFFFFFC000 +00FFFFFFFF8000 +007FFFFFFF0000 +001FFFFFFE0000 +0007FFFFF80000 +0001FFFFC00000 +00001FFE000000 +ENDCHAR +STARTCHAR 0039 +ENCODING 57 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 49 76 4 -1 +BITMAP +00003FF8000000 +0001FFFF000000 +000FFFFFC00000 +001FFFFFF00000 +007FFFFFF80000 +00FFFFFFFE0000 +01FFFFFFFF0000 +03FFFFFFFF8000 +07FFFFFFFFC000 +0FFFFFFFFFC000 +0FFFFFFFFFE000 +1FFFFFFFFFF000 +3FFFFFFFFFF000 +3FFFF01FFFF800 +3FFFC007FFF800 +7FFF8001FFFC00 +7FFF0000FFFC00 +7FFE00007FFC00 +7FFE00003FFE00 +FFFE00003FFE00 +FFFC00003FFE00 +FFFC00001FFE00 +FFFC00001FFF00 +FFFC00001FFF00 +FFFC00001FFF00 +FFFC00001FFF00 +FFFC00001FFF00 +FFFC00001FFF00 +FFFE00003FFF80 +FFFE00003FFF80 +7FFF00003FFF80 +7FFF00007FFF80 +7FFF8000FFFF80 +7FFFE003FFFF80 +3FFFF80FFFFF80 +3FFFFFFFFFFF80 +1FFFFFFFFFFF80 +1FFFFFFFFFFF80 +0FFFFFFFFFFF80 +07FFFFFFFFFF80 +03FFFFFFFFFF80 +01FFFFFFFFFF80 +00FFFFFFEFFF80 +007FFFFFCFFF80 +003FFFFF8FFF80 +000FFFFF0FFF80 +0003FFFC0FFF80 +00007FE00FFF00 +000000001FFF00 +000000001FFF00 +000000001FFF00 +000000001FFF00 +000000001FFF00 +000000003FFF00 +000000003FFE00 +001F00003FFE00 +3FFF00007FFE00 +3FFF80007FFC00 +3FFF8000FFFC00 +1FFF8000FFFC00 +1FFFC001FFF800 +1FFFE007FFF800 +1FFFF81FFFF000 +0FFFFFFFFFF000 +0FFFFFFFFFE000 +07FFFFFFFFE000 +07FFFFFFFFC000 +03FFFFFFFF8000 +03FFFFFFFF0000 +01FFFFFFFE0000 +00FFFFFFFC0000 +007FFFFFF80000 +003FFFFFE00000 +000FFFFFC00000 +0003FFFE000000 +00007FF0000000 +ENDCHAR +STARTCHAR 003A +ENCODING 58 +SWIDTH 326 0 +DWIDTH 34 0 +BBX 14 55 10 0 +BITMAP +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +ENDCHAR +STARTCHAR 003B +ENCODING 59 +SWIDTH 326 0 +DWIDTH 34 0 +BBX 15 72 9 -17 +BITMAP +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +7FFE +00FE +00FE +00FE +00FE +01FC +01FC +03FC +03F8 +07F8 +1FF0 +7FF0 +FFE0 +7FC0 +7F80 +3F00 +3C00 +1000 +ENDCHAR +STARTCHAR 003C +ENCODING 60 +SWIDTH 585 0 +DWIDTH 61 0 +BBX 51 57 4 8 +BITMAP +00000000000020 +000000000000E0 +000000000007E0 +00000000001FE0 +00000000007FE0 +0000000003FFE0 +000000000FFFE0 +000000003FFFE0 +00000000FFFFE0 +00000007FFFFE0 +0000001FFFFFE0 +0000007FFFFFE0 +000003FFFFFFE0 +00000FFFFFFFC0 +00003FFFFFFE00 +0001FFFFFFF800 +0007FFFFFFE000 +001FFFFFFF0000 +007FFFFFFC0000 +03FFFFFFE00000 +0FFFFFFF800000 +3FFFFFFE000000 +FFFFFFF0000000 +FFFFFFC0000000 +FFFFFE00000000 +FFFFF800000000 +FFFFE000000000 +FFFF0000000000 +FFFE0000000000 +FFFF8000000000 +FFFFF000000000 +FFFFFC00000000 +FFFFFF00000000 +FFFFFFE0000000 +FFFFFFF8000000 +3FFFFFFE000000 +0FFFFFFFC00000 +01FFFFFFF00000 +007FFFFFFC0000 +001FFFFFFF8000 +0007FFFFFFE000 +0000FFFFFFF800 +00003FFFFFFF00 +00000FFFFFFFC0 +000003FFFFFFE0 +0000007FFFFFE0 +0000001FFFFFE0 +00000007FFFFE0 +00000000FFFFE0 +000000003FFFE0 +000000000FFFE0 +0000000003FFE0 +00000000007FE0 +00000000001FE0 +000000000007E0 +000000000000E0 +00000000000020 +ENDCHAR +STARTCHAR 003D +ENCODING 61 +SWIDTH 585 0 +DWIDTH 61 0 +BBX 52 35 4 20 +BITMAP +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +00000000000000 +00000000000000 +00000000000000 +00000000000000 +00000000000000 +00000000000000 +00000000000000 +00000000000000 +00000000000000 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +ENDCHAR +STARTCHAR 003E +ENCODING 62 +SWIDTH 585 0 +DWIDTH 61 0 +BBX 51 57 4 8 +BITMAP +80000000000000 +E0000000000000 +FC000000000000 +FF000000000000 +FFC00000000000 +FFF80000000000 +FFFE0000000000 +FFFF8000000000 +FFFFE000000000 +FFFFFC00000000 +FFFFFF00000000 +FFFFFFC0000000 +FFFFFFF8000000 +7FFFFFFE000000 +0FFFFFFF800000 +03FFFFFFE00000 +00FFFFFFFC0000 +001FFFFFFF0000 +0007FFFFFFC000 +0001FFFFFFF800 +00003FFFFFFE00 +00000FFFFFFF80 +000003FFFFFFE0 +0000007FFFFFE0 +0000001FFFFFE0 +00000003FFFFE0 +00000000FFFFE0 +000000003FFFE0 +000000000FFFE0 +000000003FFFE0 +00000000FFFFE0 +00000007FFFFE0 +0000001FFFFFE0 +0000007FFFFFE0 +000003FFFFFFE0 +00000FFFFFFF80 +00003FFFFFFE00 +0001FFFFFFF000 +0007FFFFFFC000 +001FFFFFFF0000 +00FFFFFFFC0000 +03FFFFFFE00000 +1FFFFFFF800000 +7FFFFFFE000000 +FFFFFFF0000000 +FFFFFFC0000000 +FFFFFF00000000 +FFFFFC00000000 +FFFFE000000000 +FFFF8000000000 +FFFE0000000000 +FFF80000000000 +FFC00000000000 +FF000000000000 +FC000000000000 +E0000000000000 +80000000000000 +ENDCHAR +STARTCHAR 003F +ENCODING 63 +SWIDTH 614 0 +DWIDTH 64 0 +BBX 54 76 5 0 +BITMAP +000007FF800000 +0000FFFFFC0000 +0003FFFFFF0000 +000FFFFFFFC000 +003FFFFFFFF000 +007FFFFFFFF800 +01FFFFFFFFFE00 +03FFFFFFFFFF00 +07FFFFFFFFFF80 +0FFFFFFFFFFF80 +0FFFFFFFFFFFC0 +1FFFFF00FFFFE0 +3FFFF8001FFFF0 +3FFFE0000FFFF0 +7FFFC00007FFF8 +7FFF800003FFF8 +7FFF000001FFF8 +FFFF000001FFFC +FFFE000000FFFC +FFFE000000FFFC +FFFC000000FFFC +01FC000000FFFC +0000000000FFFC +0000000000FFFC +0000000001FFFC +0000000001FFFC +0000000003FFF8 +0000000007FFF8 +000000000FFFF8 +000000001FFFF0 +000000003FFFF0 +000000007FFFE0 +00000000FFFFC0 +00000003FFFF80 +00000007FFFF00 +0000000FFFFE00 +0000001FFFFC00 +0000003FFFF800 +0000007FFFF000 +000000FFFFE000 +000001FFFFC000 +000003FFFF8000 +000007FFFF0000 +000007FFFE0000 +00000FFFF80000 +00000FFFF00000 +00000FFFF00000 +00000FFFE00000 +00001FFFC00000 +00001FFFC00000 +00001FFF800000 +00001FFF800000 +00001FFF800000 +00001FFF800000 +00001FFF800000 +00001FFF800000 +00001FFF800000 +00000000000000 +00000000000000 +00000000000000 +00000000000000 +00000000000000 +00001FFF800000 +00001FFF800000 +00001FFF800000 +00001FFF800000 +00001FFF800000 +00001FFF800000 +00001FFF800000 +00001FFF800000 +00001FFF800000 +00001FFF800000 +00001FFF800000 +00001FFF800000 +00001FFF800000 +00001FFF800000 +ENDCHAR +STARTCHAR 0040 +ENCODING 64 +SWIDTH 969 0 +DWIDTH 101 0 +BBX 97 100 3 -24 +BITMAP +00000000001FFFE00000000000 +0000000003FFFFFF0000000000 +000000003FFFFFFFF000000000 +00000001FFFFFFFFFC00000000 +00000007FFFFFFFFFF80000000 +0000001FFFFFFFFFFFE0000000 +0000007FFFFFFFFFFFF0000000 +000001FFFFFFFFFFFFFC000000 +000007FFFFFFFFFFFFFE000000 +00000FFFFFFFFFFFFFFF800000 +00001FFFFFF0003FFFFFC00000 +00007FFFFE000001FFFFE00000 +0000FFFFE00000003FFFF00000 +0001FFFF800000000FFFF80000 +0003FFFE0000000003FFFC0000 +0007FFF80000000000FFFC0000 +000FFFE000000000007FFE0000 +000FFFC000000000003FFF0000 +001FFF8000000000000FFF0000 +003FFE00000000000007FF8000 +007FFC00007FC0000007FF8000 +007FF80003FFF80FFF83FFC000 +00FFF8001FFFFE0FFF81FFC000 +00FFF0003FFFFF1FFF80FFE000 +01FFE000FFFFFF9FFF00FFE000 +01FFC001FFFFFFDFFF007FF000 +03FF8003FFFFFFFFFF007FF000 +03FF8007FFFFFFFFFF003FF000 +07FF000FFFFFFFFFFF003FF800 +07FF001FFFF03FFFFE001FF800 +0FFE001FFFC00FFFFE001FF800 +0FFE003FFF0007FFFE001FF800 +1FFC007FFE0003FFFE001FF800 +1FFC007FFC0003FFFE000FFC00 +1FF800FFF80001FFFC000FFC00 +3FF800FFF80001FFFC000FFC00 +3FF801FFF00001FFFC000FFC00 +3FF001FFF00000FFFC000FFC00 +3FF003FFE00000FFFC000FFC00 +7FF003FFE00000FFF8000FFC00 +7FF007FFC00000FFF8000FFC00 +7FE007FFC00000FFF8000FFC00 +7FE007FFC00000FFF8000FFC00 +7FE00FFFC00000FFF8000FFC00 +FFE00FFF800000FFF0001FFC00 +FFE00FFF800000FFF0001FFC00 +FFC00FFF800000FFF0001FF800 +FFC00FFF800001FFF0001FF800 +FFC01FFF000001FFF0003FF800 +FFC01FFF000001FFE0003FF800 +FFC01FFF000001FFE0003FF000 +FFC01FFF000003FFE0007FF000 +FFC01FFF000003FFE0007FF000 +FFC01FFF000003FFE000FFE000 +FFC01FFF000003FFC000FFE000 +FFC01FFF000007FFC001FFC000 +FFC01FFF000007FFC003FFC000 +FFC01FFF00000FFFC003FF8000 +FFC01FFF00000FFFC007FF8000 +FFC01FFF80001FFF800FFF0000 +7FE00FFF80001FFF801FFF0000 +7FE00FFF80003FFF803FFE0000 +7FE00FFFC0007FFF80FFFC0000 +7FE00FFFC000FFFF81FFFC0000 +7FF007FFE001FFFFC7FFF80000 +3FF007FFF003FFFFFFFFF00000 +3FF003FFFC0FFFFFFFFFE00000 +3FF803FFFFFFFFFFFFFFC00000 +3FF801FFFFFFFFFFFFFF800000 +1FF800FFFFFFFFFFFFFF000000 +1FFC007FFFFFFFFFFFFC000000 +1FFC003FFFFFEFFFFFF8000000 +0FFE001FFFFF8FFFFFE0000000 +0FFF000FFFFF07FFFF80000000 +07FF0003FFFC03FFFC00000000 +07FF80003FE000FFC000000000 +03FFC00000000000000007FF80 +03FFC0000000000000000FFF00 +01FFE0000000000000001FFF00 +01FFF0000000000000003FFE00 +00FFF8000000000000007FFE00 +007FFC00000000000000FFFC00 +007FFF00000000000001FFF800 +003FFF80000000000007FFF000 +001FFFE000000000000FFFF000 +000FFFF800000000003FFFE000 +0007FFFE0000000000FFFFC000 +0003FFFFC000000007FFFF8000 +0001FFFFFC0000007FFFFF0000 +0000FFFFFFE0000FFFFFFE0000 +00007FFFFFFFFFFFFFFFF80000 +00001FFFFFFFFFFFFFFFF00000 +000007FFFFFFFFFFFFFFC00000 +000003FFFFFFFFFFFFFF800000 +000000FFFFFFFFFFFFFE000000 +0000001FFFFFFFFFFFF8000000 +00000007FFFFFFFFFFC0000000 +000000007FFFFFFFFE00000000 +0000000007FFFFFFE000000000 +00000000001FFFF80000000000 +ENDCHAR +STARTCHAR 0041 +ENCODING 65 +SWIDTH 681 0 +DWIDTH 71 0 +BBX 71 75 0 0 +BITMAP +0000000FFFE0000000 +0000000FFFE0000000 +0000001FFFF0000000 +0000001FFFF0000000 +0000003FFFF0000000 +0000003FFFF8000000 +0000003FFFF8000000 +0000007FFFF8000000 +0000007FFFFC000000 +0000007FFFFC000000 +000000FFFFFE000000 +000000FFFFFE000000 +000001FFFFFE000000 +000001FFFFFF000000 +000001FFFFFF000000 +000003FFFFFF800000 +000003FFFFFF800000 +000003FFFFFF800000 +000007FFEFFFC00000 +000007FFEFFFC00000 +00000FFFEFFFC00000 +00000FFFC7FFE00000 +00000FFFC7FFE00000 +00001FFFC3FFF00000 +00001FFF83FFF00000 +00001FFF83FFF00000 +00003FFF01FFF80000 +00003FFF01FFF80000 +00007FFF01FFF80000 +00007FFE00FFFC0000 +00007FFE00FFFC0000 +0000FFFE00FFFE0000 +0000FFFC007FFE0000 +0000FFFC007FFE0000 +0001FFFC003FFF0000 +0001FFF8003FFF0000 +0003FFF8003FFF0000 +0003FFF0001FFF8000 +0003FFF0001FFF8000 +0007FFF0001FFFC000 +0007FFE0000FFFC000 +0007FFE0000FFFC000 +000FFFE0000FFFE000 +000FFFC00007FFE000 +001FFFC00007FFE000 +001FFFFFFFFFFFF000 +001FFFFFFFFFFFF000 +003FFFFFFFFFFFF800 +003FFFFFFFFFFFF800 +003FFFFFFFFFFFF800 +007FFFFFFFFFFFFC00 +007FFFFFFFFFFFFC00 +00FFFFFFFFFFFFFC00 +00FFFFFFFFFFFFFE00 +00FFFFFFFFFFFFFE00 +01FFFFFFFFFFFFFF00 +01FFFFFFFFFFFFFF00 +01FFFFFFFFFFFFFF00 +03FFF80000003FFF80 +03FFF80000001FFF80 +07FFF00000001FFFC0 +07FFF00000001FFFC0 +07FFE00000000FFFC0 +0FFFE00000000FFFE0 +0FFFE00000000FFFE0 +0FFFC000000007FFE0 +1FFFC000000007FFF0 +1FFFC000000003FFF0 +3FFF8000000003FFF8 +3FFF8000000003FFF8 +3FFF8000000001FFF8 +7FFF0000000001FFFC +7FFF0000000001FFFC +7FFF0000000000FFFC +FFFE0000000000FFFE +ENDCHAR +STARTCHAR 0042 +ENCODING 66 +SWIDTH 720 0 +DWIDTH 75 0 +BBX 62 75 8 0 +BITMAP +FFFFFFFFFF800000 +FFFFFFFFFFFC0000 +FFFFFFFFFFFF8000 +FFFFFFFFFFFFC000 +FFFFFFFFFFFFF000 +FFFFFFFFFFFFF800 +FFFFFFFFFFFFFC00 +FFFFFFFFFFFFFE00 +FFFFFFFFFFFFFF00 +FFFFFFFFFFFFFF00 +FFFFFFFFFFFFFF80 +FFFFFFFFFFFFFF80 +FFFFFFFFFFFFFFC0 +FFFC000003FFFFC0 +FFFC0000007FFFC0 +FFFC0000001FFFE0 +FFFC0000000FFFE0 +FFFC0000000FFFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC0000000FFFC0 +FFFC0000000FFFC0 +FFFC0000001FFFC0 +FFFC0000003FFF80 +FFFC0000007FFF80 +FFFC000003FFFF00 +FFFFFFFFFFFFFE00 +FFFFFFFFFFFFFE00 +FFFFFFFFFFFFFC00 +FFFFFFFFFFFFF000 +FFFFFFFFFFFFE000 +FFFFFFFFFFFF8000 +FFFFFFFFFFFFF000 +FFFFFFFFFFFFFC00 +FFFFFFFFFFFFFE00 +FFFFFFFFFFFFFF00 +FFFFFFFFFFFFFF80 +FFFFFFFFFFFFFFC0 +FFFFFFFFFFFFFFE0 +FFFC000003FFFFE0 +FFFC0000003FFFF0 +FFFC0000000FFFF0 +FFFC00000003FFF8 +FFFC00000003FFF8 +FFFC00000001FFF8 +FFFC00000001FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000001FFFC +FFFC00000001FFFC +FFFC00000003FFF8 +FFFC00000007FFF8 +FFFC0000001FFFF8 +FFFC000000FFFFF0 +FFFFFFFFFFFFFFF0 +FFFFFFFFFFFFFFF0 +FFFFFFFFFFFFFFE0 +FFFFFFFFFFFFFFC0 +FFFFFFFFFFFFFFC0 +FFFFFFFFFFFFFF80 +FFFFFFFFFFFFFF00 +FFFFFFFFFFFFFE00 +FFFFFFFFFFFFFC00 +FFFFFFFFFFFFF000 +FFFFFFFFFFFFE000 +FFFFFFFFFFFF0000 +FFFFFFFFFFE00000 +ENDCHAR +STARTCHAR 0043 +ENCODING 67 +SWIDTH 720 0 +DWIDTH 75 0 +BBX 65 76 5 0 +BITMAP +0000000FFF80000000 +000000FFFFF8000000 +000007FFFFFF000000 +00003FFFFFFFC00000 +00007FFFFFFFE00000 +0001FFFFFFFFF80000 +0003FFFFFFFFFC0000 +000FFFFFFFFFFE0000 +001FFFFFFFFFFF0000 +003FFFFFFFFFFF8000 +007FFFFFFFFFFFC000 +00FFFFFFFFFFFFE000 +00FFFFFFFFFFFFF000 +01FFFFF803FFFFF000 +03FFFFC0007FFFF800 +07FFFF00001FFFF800 +07FFFC00000FFFFC00 +0FFFF8000007FFFC00 +0FFFF0000003FFFE00 +1FFFE0000001FFFE00 +1FFFC0000000FFFE00 +1FFF80000000FFFF00 +3FFF800000007FFF00 +3FFF000000007FFC00 +3FFF000000003F8000 +7FFF00000000300000 +7FFE00000000000000 +7FFE00000000000000 +7FFE00000000000000 +7FFE00000000000000 +7FFC00000000000000 +FFFC00000000000000 +FFFC00000000000000 +FFFC00000000000000 +FFFC00000000000000 +FFFC00000000000000 +FFFC00000000000000 +FFFC00000000000000 +FFFC00000000000000 +FFFC00000000000000 +FFFC00000000000000 +FFFC00000000000000 +FFFC00000000000000 +FFFC00000000000000 +FFFC00000000000000 +FFFE00000000000000 +7FFE00000000000000 +7FFE00000000100000 +7FFE000000001E0000 +7FFE000000003FC000 +7FFF000000003FF800 +3FFF000000003FFF00 +3FFF000000007FFF80 +3FFF800000007FFF80 +3FFF80000000FFFF00 +1FFFC0000000FFFF00 +1FFFE0000001FFFF00 +0FFFF0000003FFFE00 +0FFFF8000007FFFE00 +07FFFC00000FFFFC00 +07FFFE00001FFFFC00 +03FFFF80007FFFF800 +01FFFFF803FFFFF800 +01FFFFFFFFFFFFF000 +00FFFFFFFFFFFFE000 +007FFFFFFFFFFFC000 +003FFFFFFFFFFFC000 +001FFFFFFFFFFF8000 +000FFFFFFFFFFF0000 +0007FFFFFFFFFE0000 +0001FFFFFFFFF80000 +0000FFFFFFFFF00000 +00003FFFFFFFC00000 +00000FFFFFFF000000 +000001FFFFF8000000 +0000000FFF80000000 +ENDCHAR +STARTCHAR 0044 +ENCODING 68 +SWIDTH 720 0 +DWIDTH 75 0 +BBX 62 75 8 0 +BITMAP +FFFFFFFFF0000000 +FFFFFFFFFFC00000 +FFFFFFFFFFF00000 +FFFFFFFFFFFC0000 +FFFFFFFFFFFF0000 +FFFFFFFFFFFF8000 +FFFFFFFFFFFFE000 +FFFFFFFFFFFFF000 +FFFFFFFFFFFFF800 +FFFFFFFFFFFFF800 +FFFFFFFFFFFFFC00 +FFFFFFFFFFFFFE00 +FFFFFFFFFFFFFF00 +FFFC00007FFFFF00 +FFFC000007FFFF80 +FFFC000001FFFF80 +FFFC0000007FFFC0 +FFFC0000003FFFC0 +FFFC0000001FFFE0 +FFFC0000000FFFE0 +FFFC00000007FFF0 +FFFC00000007FFF0 +FFFC00000003FFF0 +FFFC00000003FFF0 +FFFC00000003FFF8 +FFFC00000001FFF8 +FFFC00000001FFF8 +FFFC00000001FFF8 +FFFC00000001FFF8 +FFFC00000000FFF8 +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000000FFFC +FFFC00000001FFF8 +FFFC00000001FFF8 +FFFC00000001FFF8 +FFFC00000001FFF8 +FFFC00000001FFF8 +FFFC00000003FFF8 +FFFC00000003FFF0 +FFFC00000007FFF0 +FFFC00000007FFF0 +FFFC0000000FFFE0 +FFFC0000000FFFE0 +FFFC0000001FFFC0 +FFFC0000003FFFC0 +FFFC000000FFFF80 +FFFC000003FFFF80 +FFFC00001FFFFF00 +FFFFFFFFFFFFFF00 +FFFFFFFFFFFFFE00 +FFFFFFFFFFFFFC00 +FFFFFFFFFFFFFC00 +FFFFFFFFFFFFF800 +FFFFFFFFFFFFF000 +FFFFFFFFFFFFE000 +FFFFFFFFFFFF8000 +FFFFFFFFFFFF0000 +FFFFFFFFFFFC0000 +FFFFFFFFFFF00000 +FFFFFFFFFF800000 +FFFFFFFFF0000000 +ENDCHAR +STARTCHAR 0045 +ENCODING 69 +SWIDTH 662 0 +DWIDTH 69 0 +BBX 56 75 8 0 +BITMAP +FFFFFFFFFFFFFE +FFFFFFFFFFFFFE +FFFFFFFFFFFFFE +FFFFFFFFFFFFFE +FFFFFFFFFFFFFE +FFFFFFFFFFFFFE +FFFFFFFFFFFFFE +FFFFFFFFFFFFFE +FFFFFFFFFFFFFE +FFFFFFFFFFFFFE +FFFFFFFFFFFFFE +FFFFFFFFFFFFFE +FFFFFFFFFFFFFE +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +FFFFFFFFFFFFFF +ENDCHAR +STARTCHAR 0046 +ENCODING 70 +SWIDTH 614 0 +DWIDTH 64 0 +BBX 51 75 8 0 +BITMAP +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFFFFFFFFFC00 +FFFFFFFFFFFC00 +FFFFFFFFFFFC00 +FFFFFFFFFFFC00 +FFFFFFFFFFFC00 +FFFFFFFFFFFC00 +FFFFFFFFFFFC00 +FFFFFFFFFFFC00 +FFFFFFFFFFFC00 +FFFFFFFFFFFC00 +FFFFFFFFFFFC00 +FFFFFFFFFFFC00 +FFFFFFFFFFFC00 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +ENDCHAR +STARTCHAR 0047 +ENCODING 71 +SWIDTH 777 0 +DWIDTH 81 0 +BBX 69 77 5 -1 +BITMAP +00000007FFF0000000 +0000007FFFFF800000 +000003FFFFFFF00000 +00001FFFFFFFFC0000 +00003FFFFFFFFF0000 +0000FFFFFFFFFF8000 +0003FFFFFFFFFFC000 +0007FFFFFFFFFFF000 +000FFFFFFFFFFFF800 +001FFFFFFFFFFFFC00 +003FFFFFFFFFFFFC00 +007FFFFFFFFFFFFE00 +00FFFFFFFFFFFFFF00 +01FFFFFE007FFFFF00 +01FFFFE0000FFFFF80 +03FFFF800003FFFFC0 +07FFFE000000FFFFC0 +07FFFC0000007FFFC0 +0FFFF80000003FFFE0 +0FFFF00000001FFFE0 +1FFFE00000000FFFE0 +1FFFC00000000FFFF0 +1FFFC000000007FFF0 +3FFF8000000007FFC0 +3FFF0000000003F800 +3FFF00000000030000 +7FFF00000000000000 +7FFE00000000000000 +7FFE00000000000000 +7FFE00000000000000 +7FFE00000000000000 +FFFC00000000000000 +FFFC00000000000000 +FFFC00000000000000 +FFFC00000000000000 +FFFC00000000000000 +FFFC000007FFFFFFF8 +FFFC000007FFFFFFF8 +FFFC000007FFFFFFF8 +FFFC000007FFFFFFF8 +FFFC000007FFFFFFF8 +FFFC000007FFFFFFF8 +FFFC000007FFFFFFF8 +FFFC000007FFFFFFF8 +FFFC000007FFFFFFF8 +7FFE000007FFFFFFF8 +7FFE000007FFFFFFF8 +7FFE000007FFFFFFF8 +7FFE000007FFFFFFF8 +7FFF0000000001FFF8 +3FFF0000000001FFF8 +3FFF0000000001FFF8 +3FFF8000000001FFF8 +3FFF8000000001FFF8 +1FFFC000000001FFF8 +1FFFE000000001FFF8 +0FFFE000000001FFF8 +0FFFF000000001FFF8 +07FFF800000003FFF8 +07FFFC00000007FFF8 +03FFFF0000001FFFF8 +03FFFF800000FFFFF8 +01FFFFF00003FFFFF8 +00FFFFFE003FFFFFF8 +00FFFFFFFFFFFFFFF8 +007FFFFFFFFFFFFFF8 +003FFFFFFFFFFFFFF0 +001FFFFFFFFFFFFFE0 +000FFFFFFFFFFFFF80 +0007FFFFFFFFFFFF00 +0001FFFFFFFFFFFC00 +0000FFFFFFFFFFF000 +00003FFFFFFFFFC000 +00000FFFFFFFFE0000 +000003FFFFFFF80000 +0000007FFFFF800000 +00000003FFF0000000 +ENDCHAR +STARTCHAR 0048 +ENCODING 72 +SWIDTH 720 0 +DWIDTH 75 0 +BBX 59 75 8 0 +BITMAP +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFFFFFFFFFFFFE0 +FFFFFFFFFFFFFFE0 +FFFFFFFFFFFFFFE0 +FFFFFFFFFFFFFFE0 +FFFFFFFFFFFFFFE0 +FFFFFFFFFFFFFFE0 +FFFFFFFFFFFFFFE0 +FFFFFFFFFFFFFFE0 +FFFFFFFFFFFFFFE0 +FFFFFFFFFFFFFFE0 +FFFFFFFFFFFFFFE0 +FFFFFFFFFFFFFFE0 +FFFFFFFFFFFFFFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +ENDCHAR +STARTCHAR 0049 +ENCODING 73 +SWIDTH 278 0 +DWIDTH 29 0 +BBX 14 75 7 0 +BITMAP +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +ENDCHAR +STARTCHAR 004A +ENCODING 74 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 48 76 2 -1 +BITMAP +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +000000003FFF +01FC00003FFF +FFFC00003FFF +FFFC00003FFF +FFFC00003FFF +FFFC00003FFF +FFFE00007FFF +FFFE00007FFE +7FFE00007FFE +7FFF00007FFE +7FFF0000FFFE +7FFF8001FFFE +7FFFC003FFFC +3FFFF80FFFFC +3FFFFFFFFFFC +1FFFFFFFFFF8 +1FFFFFFFFFF8 +0FFFFFFFFFF0 +0FFFFFFFFFE0 +07FFFFFFFFC0 +03FFFFFFFF80 +01FFFFFFFF00 +00FFFFFFFE00 +007FFFFFFC00 +001FFFFFF000 +0003FFFF8000 +00007FF80000 +ENDCHAR +STARTCHAR 004B +ENCODING 75 +SWIDTH 720 0 +DWIDTH 75 0 +BBX 66 75 8 0 +BITMAP +FFFC00000003FFFF80 +FFFC00000007FFFF00 +FFFC0000000FFFFE00 +FFFC0000001FFFFC00 +FFFC0000003FFFF800 +FFFC0000007FFFF000 +FFFC000000FFFFE000 +FFFC000001FFFFC000 +FFFC000003FFFF8000 +FFFC000007FFFF0000 +FFFC00000FFFFE0000 +FFFC00001FFFFC0000 +FFFC00003FFFF80000 +FFFC00003FFFF00000 +FFFC00007FFFE00000 +FFFC0000FFFFC00000 +FFFC0001FFFF800000 +FFFC0003FFFF000000 +FFFC0007FFFE000000 +FFFC000FFFFC000000 +FFFC001FFFF8000000 +FFFC003FFFF0000000 +FFFC007FFFE0000000 +FFFC00FFFFC0000000 +FFFC01FFFF80000000 +FFFC03FFFF80000000 +FFFC07FFFF00000000 +FFFC0FFFFE00000000 +FFFC1FFFFC00000000 +FFFC1FFFF800000000 +FFFC3FFFFC00000000 +FFFC7FFFFE00000000 +FFFCFFFFFE00000000 +FFFDFFFFFF00000000 +FFFFFFFFFF80000000 +FFFFFFFFFF80000000 +FFFFFFFFFFC0000000 +FFFFFFFFFFC0000000 +FFFFFFFFFFE0000000 +FFFFFFFFFFF0000000 +FFFFFFFFFFF0000000 +FFFFFFBFFFF8000000 +FFFFFF1FFFFC000000 +FFFFFE1FFFFC000000 +FFFFFC0FFFFE000000 +FFFFF807FFFF000000 +FFFFF007FFFF000000 +FFFFE003FFFF800000 +FFFFC003FFFFC00000 +FFFF8001FFFFC00000 +FFFF0000FFFFE00000 +FFFE0000FFFFE00000 +FFFC00007FFFF00000 +FFFC00007FFFF80000 +FFFC00003FFFF80000 +FFFC00001FFFFC0000 +FFFC00001FFFFE0000 +FFFC00000FFFFE0000 +FFFC00000FFFFF0000 +FFFC000007FFFF8000 +FFFC000003FFFF8000 +FFFC000003FFFFC000 +FFFC000001FFFFC000 +FFFC000000FFFFE000 +FFFC000000FFFFF000 +FFFC0000007FFFF000 +FFFC0000007FFFF800 +FFFC0000003FFFFC00 +FFFC0000001FFFFC00 +FFFC0000001FFFFE00 +FFFC0000000FFFFF00 +FFFC0000000FFFFF00 +FFFC00000007FFFF80 +FFFC00000003FFFFC0 +FFFC00000003FFFFC0 +ENDCHAR +STARTCHAR 004C +ENCODING 76 +SWIDTH 614 0 +DWIDTH 64 0 +BBX 53 75 8 0 +BITMAP +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFFFFFFFFFFF8 +FFFFFFFFFFFFF8 +FFFFFFFFFFFFF8 +FFFFFFFFFFFFF8 +FFFFFFFFFFFFF8 +FFFFFFFFFFFFF8 +FFFFFFFFFFFFF8 +FFFFFFFFFFFFF8 +FFFFFFFFFFFFF8 +FFFFFFFFFFFFF8 +FFFFFFFFFFFFF8 +FFFFFFFFFFFFF8 +FFFFFFFFFFFFF8 +ENDCHAR +STARTCHAR 004D +ENCODING 77 +SWIDTH 835 0 +DWIDTH 87 0 +BBX 73 75 7 0 +BITMAP +FFFFFF0000007FFFFF80 +FFFFFF0000007FFFFF80 +FFFFFF800000FFFFFF80 +FFFFFF800000FFFFFF80 +FFFFFF800000FFFFFF80 +FFFFFF800000FFFFFF80 +FFFFFFC00001FFFFFF80 +FFFFFFC00001FFFFFF80 +FFFFFFC00001FFFFFF80 +FFFFFFC00001FFFFFF80 +FFFFFFE00003FFFFFF80 +FFFFFFE00003FFFFFF80 +FFFFFFE00003FFFFFF80 +FFFFFFE00003FFFFFF80 +FFFFFFF00007FFFFFF80 +FFFFFFF00007FFFFFF80 +FFFFFFF00007FFDFFF80 +FFFFFFF00007FFDFFF80 +FFFDFFF8000FFFDFFF80 +FFFDFFF8000FFFDFFF80 +FFFCFFF8000FFF9FFF80 +FFFCFFF8000FFF9FFF80 +FFFCFFFC001FFF9FFF80 +FFFCFFFC001FFF9FFF80 +FFFC7FFC001FFF9FFF80 +FFFC7FFC001FFF1FFF80 +FFFC7FFE003FFF1FFF80 +FFFC7FFE003FFF1FFF80 +FFFC7FFE003FFF1FFF80 +FFFC3FFE003FFE1FFF80 +FFFC3FFE003FFE1FFF80 +FFFC3FFF007FFE1FFF80 +FFFC3FFF007FFE1FFF80 +FFFC1FFF007FFC1FFF80 +FFFC1FFF007FFC1FFF80 +FFFC1FFF80FFFC1FFF80 +FFFC1FFF80FFFC1FFF80 +FFFC0FFF80FFF81FFF80 +FFFC0FFF80FFF81FFF80 +FFFC0FFFC1FFF81FFF80 +FFFC0FFFC1FFF81FFF80 +FFFC0FFFC1FFF81FFF80 +FFFC07FFC1FFF01FFF80 +FFFC07FFE3FFF01FFF80 +FFFC07FFE3FFF01FFF80 +FFFC07FFE3FFF01FFF80 +FFFC03FFE3FFE01FFF80 +FFFC03FFF7FFE01FFF80 +FFFC03FFF7FFE01FFF80 +FFFC03FFF7FFE01FFF80 +FFFC01FFF7FFC01FFF80 +FFFC01FFFFFFC01FFF80 +FFFC01FFFFFFC01FFF80 +FFFC01FFFFFFC01FFF80 +FFFC00FFFFFF801FFF80 +FFFC00FFFFFF801FFF80 +FFFC00FFFFFF801FFF80 +FFFC00FFFFFF801FFF80 +FFFC00FFFFFF801FFF80 +FFFC007FFFFF001FFF80 +FFFC007FFFFF001FFF80 +FFFC007FFFFF001FFF80 +FFFC007FFFFF001FFF80 +FFFC003FFFFE001FFF80 +FFFC003FFFFE001FFF80 +FFFC003FFFFE001FFF80 +FFFC003FFFFE001FFF80 +FFFC001FFFFC001FFF80 +FFFC001FFFFC001FFF80 +FFFC001FFFFC001FFF80 +FFFC001FFFFC001FFF80 +FFFC000FFFF8001FFF80 +FFFC000FFFF8001FFF80 +FFFC000FFFF8001FFF80 +FFFC000FFFF8001FFF80 +ENDCHAR +STARTCHAR 004E +ENCODING 78 +SWIDTH 720 0 +DWIDTH 75 0 +BBX 59 75 8 0 +BITMAP +FFFE00000007FFE0 +FFFF00000007FFE0 +FFFF00000007FFE0 +FFFF80000007FFE0 +FFFF80000007FFE0 +FFFFC0000007FFE0 +FFFFE0000007FFE0 +FFFFE0000007FFE0 +FFFFF0000007FFE0 +FFFFF0000007FFE0 +FFFFF8000007FFE0 +FFFFFC000007FFE0 +FFFFFC000007FFE0 +FFFFFE000007FFE0 +FFFFFE000007FFE0 +FFFFFF000007FFE0 +FFFFFF800007FFE0 +FFFFFF800007FFE0 +FFFFFFC00007FFE0 +FFFFFFC00007FFE0 +FFFFFFE00007FFE0 +FFFFFFF00007FFE0 +FFFFFFF00007FFE0 +FFFFFFF80007FFE0 +FFFFFFF80007FFE0 +FFFFFFFC0007FFE0 +FFFDFFFE0007FFE0 +FFFDFFFE0007FFE0 +FFFCFFFF0007FFE0 +FFFCFFFF0007FFE0 +FFFC7FFF8007FFE0 +FFFC3FFFC007FFE0 +FFFC3FFFC007FFE0 +FFFC1FFFE007FFE0 +FFFC1FFFE007FFE0 +FFFC0FFFF007FFE0 +FFFC07FFF807FFE0 +FFFC07FFF807FFE0 +FFFC03FFFC07FFE0 +FFFC03FFFE07FFE0 +FFFC01FFFE07FFE0 +FFFC00FFFF07FFE0 +FFFC00FFFF07FFE0 +FFFC007FFF87FFE0 +FFFC007FFFC7FFE0 +FFFC003FFFC7FFE0 +FFFC001FFFE7FFE0 +FFFC001FFFE7FFE0 +FFFC000FFFF7FFE0 +FFFC000FFFFFFFE0 +FFFC0007FFFFFFE0 +FFFC0003FFFFFFE0 +FFFC0003FFFFFFE0 +FFFC0001FFFFFFE0 +FFFC0000FFFFFFE0 +FFFC0000FFFFFFE0 +FFFC00007FFFFFE0 +FFFC00007FFFFFE0 +FFFC00003FFFFFE0 +FFFC00001FFFFFE0 +FFFC00001FFFFFE0 +FFFC00000FFFFFE0 +FFFC00000FFFFFE0 +FFFC000007FFFFE0 +FFFC000003FFFFE0 +FFFC000003FFFFE0 +FFFC000001FFFFE0 +FFFC000001FFFFE0 +FFFC000000FFFFE0 +FFFC0000007FFFE0 +FFFC0000007FFFE0 +FFFC0000003FFFE0 +FFFC0000003FFFE0 +FFFC0000001FFFE0 +FFFC0000000FFFE0 +ENDCHAR +STARTCHAR 004F +ENCODING 79 +SWIDTH 777 0 +DWIDTH 81 0 +BBX 71 77 5 -1 +BITMAP +0000000FFFC0000000 +000000FFFFFE000000 +000007FFFFFFC00000 +00003FFFFFFFF00000 +00007FFFFFFFFC0000 +0001FFFFFFFFFF0000 +0003FFFFFFFFFF8000 +000FFFFFFFFFFFC000 +001FFFFFFFFFFFE000 +003FFFFFFFFFFFF800 +007FFFFFFFFFFFFC00 +007FFFFFFFFFFFFC00 +00FFFFFFFFFFFFFE00 +01FFFFFE007FFFFF00 +03FFFFE0000FFFFF80 +03FFFF800003FFFF80 +07FFFE000000FFFFC0 +0FFFFC0000007FFFC0 +0FFFF80000003FFFE0 +1FFFF00000001FFFE0 +1FFFE00000000FFFF0 +1FFFC000000007FFF0 +3FFFC000000007FFF8 +3FFF8000000003FFF8 +3FFF8000000001FFF8 +7FFF0000000001FFF8 +7FFF0000000001FFFC +7FFE0000000000FFFC +7FFE0000000000FFFC +7FFE0000000000FFFC +7FFE0000000000FFFC +FFFE0000000000FFFE +FFFC00000000007FFE +FFFC00000000007FFE +FFFC00000000007FFE +FFFC00000000007FFE +FFFC00000000007FFE +FFFC00000000007FFE +FFFC00000000007FFE +FFFC00000000007FFE +FFFC00000000007FFE +FFFC00000000007FFE +FFFC00000000007FFE +FFFC00000000007FFE +FFFC00000000007FFE +FFFE0000000000FFFE +FFFE0000000000FFFC +7FFE0000000000FFFC +7FFE0000000000FFFC +7FFF0000000001FFFC +7FFF0000000001FFFC +7FFF0000000001FFFC +3FFF8000000003FFF8 +3FFF8000000003FFF8 +3FFFC000000007FFF8 +1FFFC000000007FFF0 +1FFFE00000000FFFF0 +1FFFF00000001FFFE0 +0FFFF80000003FFFE0 +0FFFFC0000007FFFE0 +07FFFF000000FFFFC0 +07FFFF800003FFFF80 +03FFFFE0000FFFFF80 +01FFFFFE007FFFFF00 +00FFFFFFFFFFFFFE00 +00FFFFFFFFFFFFFE00 +007FFFFFFFFFFFFC00 +003FFFFFFFFFFFF800 +001FFFFFFFFFFFF000 +000FFFFFFFFFFFE000 +0003FFFFFFFFFF8000 +0001FFFFFFFFFF0000 +00007FFFFFFFFC0000 +00001FFFFFFFF00000 +000007FFFFFFC00000 +000000FFFFFE000000 +00000007FFC0000000 +ENDCHAR +STARTCHAR 0050 +ENCODING 80 +SWIDTH 662 0 +DWIDTH 69 0 +BBX 56 75 8 0 +BITMAP +FFFFFFFFF80000 +FFFFFFFFFFC000 +FFFFFFFFFFF800 +FFFFFFFFFFFC00 +FFFFFFFFFFFF00 +FFFFFFFFFFFF80 +FFFFFFFFFFFFC0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFF8 +FFFFFFFFFFFFFC +FFFFFFFFFFFFFC +FFFC00007FFFFC +FFFC00000FFFFE +FFFC000003FFFE +FFFC000001FFFE +FFFC000000FFFE +FFFC0000007FFF +FFFC0000007FFF +FFFC0000003FFF +FFFC0000003FFF +FFFC0000003FFF +FFFC0000003FFF +FFFC0000003FFF +FFFC0000003FFF +FFFC0000003FFF +FFFC0000007FFF +FFFC0000007FFF +FFFC000000FFFE +FFFC000001FFFE +FFFC000003FFFE +FFFC00000FFFFE +FFFC0000FFFFFC +FFFFFFFFFFFFFC +FFFFFFFFFFFFF8 +FFFFFFFFFFFFF8 +FFFFFFFFFFFFF0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFC0 +FFFFFFFFFFFF80 +FFFFFFFFFFFF00 +FFFFFFFFFFFE00 +FFFFFFFFFFF800 +FFFFFFFFFFE000 +FFFFFFFFFF8000 +FFFFFFFFE00000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +ENDCHAR +STARTCHAR 0051 +ENCODING 81 +SWIDTH 777 0 +DWIDTH 81 0 +BBX 74 83 5 -7 +BITMAP +00000007FFC000000000 +000000FFFFFE00000000 +000007FFFFFFC0000000 +00001FFFFFFFF0000000 +00007FFFFFFFFC000000 +0001FFFFFFFFFF000000 +0003FFFFFFFFFF800000 +000FFFFFFFFFFFE00000 +001FFFFFFFFFFFF00000 +003FFFFFFFFFFFF80000 +007FFFFFFFFFFFFC0000 +00FFFFFFFFFFFFFE0000 +00FFFFFFFFFFFFFE0000 +01FFFFFE007FFFFF0000 +03FFFFE0000FFFFF8000 +03FFFF800003FFFFC000 +07FFFE000000FFFFC000 +0FFFFC0000007FFFE000 +0FFFF80000003FFFE000 +1FFFF00000001FFFF000 +1FFFE00000000FFFF000 +1FFFC000000007FFF000 +3FFFC000000007FFF800 +3FFF8000000003FFF800 +3FFF8000000003FFF800 +7FFF0000000001FFFC00 +7FFF0000000001FFFC00 +7FFE0000000000FFFC00 +7FFE0000000000FFFC00 +7FFE0000000000FFFC00 +FFFE0000000000FFFC00 +FFFC0000000000FFFE00 +FFFC00000000007FFE00 +FFFC00000000007FFE00 +FFFC00000000007FFE00 +FFFC00000000007FFE00 +FFFC00000000007FFE00 +FFFC00000000007FFE00 +FFFC00000000007FFE00 +FFFC00000000007FFE00 +FFFC00000000007FFE00 +FFFC00000000007FFE00 +FFFC00000000007FFE00 +FFFC00000000007FFE00 +FFFC0000000000FFFE00 +FFFE0000000000FFFE00 +7FFE0000000000FFFC00 +7FFE0000000000FFFC00 +7FFE0000000000FFFC00 +7FFE0000000001FFFC00 +7FFF00000C0001FFFC00 +7FFF00001F0003FFF800 +3FFF80001FC003FFF800 +3FFF80001FF007FFF800 +3FFFC0003FFC07FFF800 +1FFFC0003FFE0FFFF000 +1FFFE0007FFF9FFFF000 +1FFFF0007FFFFFFFE000 +0FFFF800FFFFFFFFE000 +0FFFFC007FFFFFFFC000 +07FFFE000FFFFFFFC000 +07FFFF8003FFFFFF8000 +03FFFFE000FFFFFF8000 +01FFFFFC01FFFFFF0000 +01FFFFFFFFFFFFFE0000 +00FFFFFFFFFFFFFC0000 +007FFFFFFFFFFFFE0000 +003FFFFFFFFFFFFF8000 +001FFFFFFFFFFFFFC000 +000FFFFFFFFFFFFFF000 +0003FFFFFFFFFFFFFC00 +0001FFFFFFFFFFFFFF80 +00007FFFFFFFFFFFFFC0 +00001FFFFFFFFFFFFF80 +000007FFFFFFC7FFFF80 +000000FFFFFE01FFFF00 +00000007FFE000FFFF00 +000000000000003FFE00 +000000000000001FFE00 +0000000000000007FC00 +0000000000000003FC00 +0000000000000000F800 +00000000000000001800 +ENDCHAR +STARTCHAR 0052 +ENCODING 82 +SWIDTH 720 0 +DWIDTH 75 0 +BBX 66 75 8 0 +BITMAP +FFFFFFFFFF80000000 +FFFFFFFFFFFE000000 +FFFFFFFFFFFF800000 +FFFFFFFFFFFFE00000 +FFFFFFFFFFFFF80000 +FFFFFFFFFFFFFC0000 +FFFFFFFFFFFFFE0000 +FFFFFFFFFFFFFF0000 +FFFFFFFFFFFFFF0000 +FFFFFFFFFFFFFF8000 +FFFFFFFFFFFFFF8000 +FFFFFFFFFFFFFFC000 +FFFFFFFFFFFFFFC000 +FFFC000001FFFFE000 +FFFC0000003FFFE000 +FFFC0000001FFFE000 +FFFC0000000FFFF000 +FFFC00000007FFF000 +FFFC00000007FFF000 +FFFC00000003FFF000 +FFFC00000003FFF000 +FFFC00000003FFF000 +FFFC00000003FFF000 +FFFC00000003FFF000 +FFFC00000003FFF000 +FFFC00000007FFF000 +FFFC00000007FFE000 +FFFC0000000FFFE000 +FFFC0000001FFFE000 +FFFC0000003FFFE000 +FFFC000003FFFFC000 +FFFFFFFFFFFFFFC000 +FFFFFFFFFFFFFF8000 +FFFFFFFFFFFFFF8000 +FFFFFFFFFFFFFF0000 +FFFFFFFFFFFFFE0000 +FFFFFFFFFFFFFC0000 +FFFFFFFFFFFFF80000 +FFFFFFFFFFFFF00000 +FFFFFFFFFFFFC00000 +FFFFFFFFFFFF000000 +FFFFFFFFFFF0000000 +FFFFFFFFFFC0000000 +FFFFFFFFFFF0000000 +FFFC00FFFFF8000000 +FFFC001FFFFC000000 +FFFC0007FFFE000000 +FFFC0003FFFF000000 +FFFC0001FFFF800000 +FFFC0000FFFFC00000 +FFFC00007FFFE00000 +FFFC00003FFFE00000 +FFFC00001FFFF00000 +FFFC00001FFFF80000 +FFFC00000FFFF80000 +FFFC000007FFFC0000 +FFFC000003FFFE0000 +FFFC000001FFFE0000 +FFFC000001FFFF0000 +FFFC000000FFFF0000 +FFFC0000007FFF8000 +FFFC0000007FFFC000 +FFFC0000003FFFC000 +FFFC0000003FFFE000 +FFFC0000001FFFE000 +FFFC0000000FFFF000 +FFFC0000000FFFF800 +FFFC00000007FFF800 +FFFC00000003FFFC00 +FFFC00000003FFFE00 +FFFC00000001FFFE00 +FFFC00000001FFFF00 +FFFC00000000FFFF00 +FFFC000000007FFF80 +FFFC000000007FFFC0 +ENDCHAR +STARTCHAR 0053 +ENCODING 83 +SWIDTH 662 0 +DWIDTH 69 0 +BBX 60 77 4 -1 +BITMAP +000001FFF0000000 +00003FFFFF800000 +0001FFFFFFF00000 +0007FFFFFFFC0000 +000FFFFFFFFE0000 +003FFFFFFFFF8000 +007FFFFFFFFFC000 +00FFFFFFFFFFE000 +01FFFFFFFFFFF000 +01FFFFFFFFFFF800 +03FFFFFFFFFFF800 +07FFFFFFFFFFFC00 +07FFFFFFFFFFFC00 +0FFFFF803FFFFE00 +0FFFF80007FFFE00 +0FFFF00001FFFF00 +1FFFE00000FFFF00 +1FFFC000007FFF00 +1FFF8000007FFF00 +1FFF8000003FFF80 +1FFF8000003FFF80 +1FFF8000003FFF80 +1FFF8000001FFF80 +1FFFC000001FC000 +1FFFE00000000000 +1FFFF00000000000 +0FFFFC0000000000 +0FFFFF0000000000 +0FFFFFE000000000 +07FFFFFE00000000 +07FFFFFFE0000000 +03FFFFFFFE000000 +01FFFFFFFFE00000 +01FFFFFFFFF80000 +00FFFFFFFFFF0000 +007FFFFFFFFFC000 +003FFFFFFFFFE000 +000FFFFFFFFFF800 +0007FFFFFFFFFC00 +0001FFFFFFFFFE00 +00003FFFFFFFFF00 +000007FFFFFFFF00 +000000FFFFFFFF80 +0000000FFFFFFFC0 +00000000FFFFFFC0 +000000000FFFFFC0 +0000000001FFFFE0 +00000000003FFFE0 +00000000001FFFE0 +00000000000FFFF0 +01FC00000007FFF0 +FFFC00000003FFF0 +FFFE00000003FFF0 +FFFE00000003FFF0 +7FFE00000003FFF0 +7FFF00000003FFF0 +7FFF00000003FFF0 +7FFF80000007FFF0 +3FFF80000007FFF0 +3FFFC000000FFFE0 +3FFFE000001FFFE0 +1FFFF800007FFFE0 +1FFFFE0000FFFFC0 +0FFFFFC00FFFFFC0 +0FFFFFFFFFFFFF80 +07FFFFFFFFFFFF80 +07FFFFFFFFFFFF00 +03FFFFFFFFFFFF00 +01FFFFFFFFFFFE00 +00FFFFFFFFFFFC00 +007FFFFFFFFFF800 +003FFFFFFFFFE000 +000FFFFFFFFFC000 +0003FFFFFFFF0000 +0000FFFFFFFC0000 +00001FFFFFE00000 +000001FFFC000000 +ENDCHAR +STARTCHAR 0054 +ENCODING 84 +SWIDTH 604 0 +DWIDTH 63 0 +BBX 58 75 3 0 +BITMAP +FFFFFFFFFFFFFFC0 +FFFFFFFFFFFFFFC0 +FFFFFFFFFFFFFFC0 +FFFFFFFFFFFFFFC0 +FFFFFFFFFFFFFFC0 +FFFFFFFFFFFFFFC0 +FFFFFFFFFFFFFFC0 +FFFFFFFFFFFFFFC0 +FFFFFFFFFFFFFFC0 +FFFFFFFFFFFFFFC0 +FFFFFFFFFFFFFFC0 +FFFFFFFFFFFFFFC0 +FFFFFFFFFFFFFFC0 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +000003FFF0000000 +ENDCHAR +STARTCHAR 0055 +ENCODING 85 +SWIDTH 720 0 +DWIDTH 75 0 +BBX 59 76 8 -1 +BITMAP +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC00000007FFE0 +FFFC0000000FFFE0 +7FFE0000000FFFC0 +7FFE0000000FFFC0 +7FFE0000000FFFC0 +7FFF0000001FFFC0 +7FFF8000001FFFC0 +7FFF8000003FFFC0 +3FFFC000007FFF80 +3FFFF00000FFFF80 +3FFFFC0003FFFF80 +1FFFFF801FFFFF00 +1FFFFFFFFFFFFF00 +0FFFFFFFFFFFFE00 +0FFFFFFFFFFFFE00 +07FFFFFFFFFFFC00 +03FFFFFFFFFFF800 +01FFFFFFFFFFF800 +00FFFFFFFFFFF000 +007FFFFFFFFFC000 +001FFFFFFFFF8000 +000FFFFFFFFE0000 +0003FFFFFFF80000 +00007FFFFFC00000 +000003FFFC000000 +ENDCHAR +STARTCHAR 0056 +ENCODING 86 +SWIDTH 662 0 +DWIDTH 69 0 +BBX 69 75 0 0 +BITMAP +FFFE0000000003FFF8 +7FFE0000000003FFF0 +7FFF0000000007FFF0 +7FFF0000000007FFF0 +3FFF0000000007FFE0 +3FFF800000000FFFE0 +3FFF800000000FFFE0 +1FFF800000000FFFC0 +1FFFC00000001FFFC0 +1FFFC00000001FFFC0 +0FFFC00000003FFF80 +0FFFE00000003FFF80 +07FFE00000003FFF00 +07FFF00000007FFF00 +07FFF00000007FFF00 +03FFF00000007FFE00 +03FFF8000000FFFE00 +03FFF8000000FFFE00 +01FFF8000000FFFC00 +01FFFC000001FFFC00 +01FFFC000001FFFC00 +00FFFC000001FFF800 +00FFFE000003FFF800 +007FFE000003FFF000 +007FFE000003FFF000 +007FFF000007FFF000 +003FFF000007FFE000 +003FFF000007FFE000 +003FFF80000FFFE000 +001FFF80000FFFC000 +001FFFC0001FFFC000 +000FFFC0001FFF8000 +000FFFC0001FFF8000 +000FFFE0003FFF8000 +0007FFE0003FFF0000 +0007FFE0003FFF0000 +0007FFF0007FFF0000 +0003FFF0007FFE0000 +0003FFF0007FFE0000 +0003FFF800FFFE0000 +0001FFF800FFFC0000 +0001FFF800FFFC0000 +0000FFFC01FFF80000 +0000FFFC01FFF80000 +0000FFFC01FFF80000 +00007FFE03FFF00000 +00007FFE03FFF00000 +00007FFF07FFF00000 +00003FFF07FFE00000 +00003FFF07FFE00000 +00003FFF8FFFE00000 +00001FFF8FFFC00000 +00001FFF8FFFC00000 +00000FFFDFFF800000 +00000FFFDFFF800000 +00000FFFDFFF800000 +000007FFFFFF000000 +000007FFFFFF000000 +000007FFFFFF000000 +000003FFFFFE000000 +000003FFFFFE000000 +000001FFFFFE000000 +000001FFFFFC000000 +000001FFFFFC000000 +000000FFFFF8000000 +000000FFFFF8000000 +000000FFFFF8000000 +0000007FFFF0000000 +0000007FFFF0000000 +0000007FFFF0000000 +0000003FFFE0000000 +0000003FFFE0000000 +0000001FFFC0000000 +0000001FFFC0000000 +0000001FFFC0000000 +ENDCHAR +STARTCHAR 0057 +ENCODING 87 +SWIDTH 950 0 +DWIDTH 99 0 +BBX 99 75 0 0 +BITMAP +FFFC000000FFFFE000000FFFE0 +FFFE000000FFFFE000000FFFE0 +7FFE000000FFFFE000000FFFC0 +7FFE000001FFFFF000000FFFC0 +7FFE000001FFFFF000000FFFC0 +7FFF000001FFFFF000001FFFC0 +3FFF000003FFFFF800001FFF80 +3FFF000003FFFFF800001FFF80 +3FFF000003FFFFF800001FFF80 +3FFF800003FFFFF800003FFF80 +1FFF800007FFFFFC00003FFF00 +1FFF800007FFFFFC00003FFF00 +1FFF800007FFFFFC00003FFF00 +1FFFC00007FFFFFC00007FFF00 +0FFFC0000FFFFFFE00007FFE00 +0FFFC0000FFFFFFE00007FFE00 +0FFFC0000FFFFFFE00007FFE00 +0FFFC0000FFFFFFE00007FFE00 +07FFE0001FFFFFFF0000FFFC00 +07FFE0001FFFBFFF0000FFFC00 +07FFE0001FFFBFFF0000FFFC00 +07FFE0003FFFBFFF0000FFFC00 +03FFF0003FFFBFFF8001FFFC00 +03FFF0003FFF1FFF8001FFF800 +03FFF0003FFF1FFF8001FFF800 +03FFF0007FFF1FFF8001FFF800 +01FFF8007FFF1FFFC003FFF800 +01FFF8007FFE0FFFC003FFF000 +01FFF8007FFE0FFFC003FFF000 +01FFF800FFFE0FFFE003FFF000 +00FFFC00FFFC07FFE003FFF000 +00FFFC00FFFC07FFE007FFE000 +00FFFC00FFFC07FFE007FFE000 +00FFFC01FFFC07FFF007FFE000 +007FFC01FFF803FFF007FFE000 +007FFE01FFF803FFF00FFFC000 +007FFE03FFF803FFF00FFFC000 +007FFE03FFF803FFF80FFFC000 +003FFE03FFF001FFF80FFFC000 +003FFF03FFF001FFF81FFF8000 +003FFF07FFF001FFF81FFF8000 +003FFF07FFF001FFFC1FFF8000 +001FFF07FFE000FFFC1FFF8000 +001FFF87FFE000FFFC1FFF0000 +001FFF8FFFE000FFFC3FFF0000 +001FFF8FFFC000FFFE3FFF0000 +000FFF8FFFC0007FFE3FFF0000 +000FFFCFFFC0007FFE3FFE0000 +000FFFDFFFC0007FFE7FFE0000 +000FFFDFFF80003FFF7FFE0000 +0007FFDFFF80003FFF7FFE0000 +0007FFFFFF80003FFF7FFC0000 +0007FFFFFF80003FFFFFFC0000 +0007FFFFFF00001FFFFFFC0000 +0003FFFFFF00001FFFFFFC0000 +0003FFFFFF00001FFFFFF80000 +0003FFFFFF00001FFFFFF80000 +0003FFFFFE00000FFFFFF80000 +0001FFFFFE00000FFFFFF80000 +0001FFFFFE00000FFFFFF00000 +0001FFFFFC00000FFFFFF00000 +0001FFFFFC000007FFFFF00000 +0000FFFFFC000007FFFFF00000 +0000FFFFFC000007FFFFE00000 +0000FFFFF8000007FFFFE00000 +0000FFFFF8000003FFFFE00000 +00007FFFF8000003FFFFE00000 +00007FFFF8000003FFFFC00000 +00007FFFF0000003FFFFC00000 +00007FFFF0000001FFFFC00000 +00003FFFF0000001FFFFC00000 +00003FFFF0000001FFFF800000 +00003FFFE0000000FFFF800000 +00003FFFE0000000FFFF800000 +00001FFFE0000000FFFF800000 +ENDCHAR +STARTCHAR 0058 +ENCODING 88 +SWIDTH 662 0 +DWIDTH 69 0 +BBX 67 75 1 0 +BITMAP +1FFFE0000000FFFF00 +1FFFF0000001FFFF00 +0FFFF0000001FFFE00 +07FFF8000003FFFC00 +07FFFC000007FFFC00 +03FFFC000007FFF800 +01FFFE00000FFFF000 +01FFFF00001FFFF000 +00FFFF00001FFFE000 +007FFF80003FFFC000 +007FFFC0007FFFC000 +003FFFC0007FFF8000 +001FFFE000FFFF0000 +001FFFF001FFFF0000 +000FFFF001FFFE0000 +0007FFF803FFFC0000 +0007FFFC07FFFC0000 +0003FFFC07FFF80000 +0001FFFE0FFFF80000 +0001FFFE1FFFF00000 +0000FFFF1FFFE00000 +0000FFFFBFFFE00000 +00007FFFBFFFC00000 +00003FFFFFFF800000 +00003FFFFFFF800000 +00001FFFFFFF000000 +00000FFFFFFE000000 +00000FFFFFFE000000 +000007FFFFFC000000 +000003FFFFF8000000 +000003FFFFF8000000 +000001FFFFF0000000 +000000FFFFE0000000 +000000FFFFE0000000 +0000007FFFC0000000 +0000007FFFC0000000 +000000FFFFE0000000 +000000FFFFE0000000 +000001FFFFF0000000 +000001FFFFF0000000 +000003FFFFF8000000 +000007FFFFFC000000 +000007FFFFFC000000 +00000FFFFFFE000000 +00001FFFFFFF000000 +00001FFFFFFF000000 +00003FFFFFFF800000 +00007FFFFFFFC00000 +00007FFFBFFFC00000 +0000FFFF1FFFE00000 +0001FFFF1FFFF00000 +0001FFFE0FFFF00000 +0003FFFC07FFF80000 +0007FFFC07FFFC0000 +0007FFF803FFFC0000 +000FFFF803FFFE0000 +001FFFF001FFFE0000 +001FFFE000FFFF0000 +003FFFE000FFFF8000 +003FFFC0007FFF8000 +007FFF80003FFFC000 +00FFFF80003FFFE000 +00FFFF00001FFFE000 +01FFFE00000FFFF000 +03FFFE00000FFFF800 +03FFFC000007FFF800 +07FFF8000003FFFC00 +0FFFF8000003FFFE00 +0FFFF0000001FFFE00 +1FFFE0000000FFFF00 +3FFFE0000000FFFF80 +3FFFC00000007FFF80 +7FFF800000003FFFC0 +FFFF800000003FFFE0 +FFFF000000001FFFE0 +ENDCHAR +STARTCHAR 0059 +ENCODING 89 +SWIDTH 652 0 +DWIDTH 68 0 +BBX 68 75 0 0 +BITMAP +FFFF000000000FFFF0 +FFFF800000001FFFF0 +7FFF800000001FFFE0 +3FFFC00000003FFFC0 +3FFFC00000007FFFC0 +1FFFE00000007FFF80 +0FFFF0000000FFFF00 +0FFFF0000000FFFF00 +07FFF8000001FFFE00 +03FFF8000001FFFE00 +03FFFC000003FFFC00 +01FFFE000007FFF800 +01FFFE000007FFF800 +00FFFF00000FFFF000 +007FFF00000FFFE000 +007FFF80001FFFE000 +003FFF80001FFFC000 +001FFFC0003FFF8000 +001FFFE0007FFF8000 +000FFFE0007FFF0000 +000FFFF000FFFF0000 +0007FFF000FFFE0000 +0003FFF801FFFC0000 +0003FFF801FFFC0000 +0001FFFC03FFF80000 +0000FFFE07FFF00000 +0000FFFE07FFF00000 +00007FFF0FFFE00000 +00003FFF0FFFE00000 +00003FFF9FFFC00000 +00001FFFBFFF800000 +00001FFFFFFF800000 +00000FFFFFFF000000 +000007FFFFFE000000 +000007FFFFFE000000 +000003FFFFFC000000 +000001FFFFF8000000 +000001FFFFF8000000 +000000FFFFF0000000 +0000007FFFF0000000 +0000007FFFE0000000 +0000003FFFC0000000 +0000003FFFC0000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +0000001FFF80000000 +ENDCHAR +STARTCHAR 005A +ENCODING 90 +SWIDTH 614 0 +DWIDTH 64 0 +BBX 61 75 1 0 +BITMAP +07FFFFFFFFFFFFF0 +07FFFFFFFFFFFFF0 +07FFFFFFFFFFFFF0 +07FFFFFFFFFFFFF0 +07FFFFFFFFFFFFF0 +07FFFFFFFFFFFFF0 +07FFFFFFFFFFFFF0 +07FFFFFFFFFFFFF0 +07FFFFFFFFFFFFF0 +07FFFFFFFFFFFFF0 +07FFFFFFFFFFFFF0 +07FFFFFFFFFFFFF0 +07FFFFFFFFFFFFF0 +00000000003FFFF0 +00000000007FFFE0 +0000000000FFFFC0 +0000000001FFFF80 +0000000003FFFF00 +0000000007FFFE00 +000000000FFFFC00 +000000000FFFF800 +000000001FFFF800 +000000003FFFF000 +000000007FFFE000 +00000000FFFFC000 +00000001FFFF8000 +00000003FFFF0000 +00000007FFFE0000 +0000000FFFFC0000 +0000000FFFFC0000 +0000001FFFF80000 +0000003FFFF00000 +0000007FFFE00000 +000000FFFFC00000 +000001FFFF800000 +000003FFFF000000 +000007FFFE000000 +000007FFFE000000 +00000FFFFC000000 +00001FFFF8000000 +00003FFFF0000000 +00007FFFE0000000 +0000FFFFC0000000 +0001FFFF80000000 +0003FFFF00000000 +0003FFFF00000000 +0007FFFE00000000 +000FFFFC00000000 +001FFFF800000000 +003FFFF000000000 +007FFFE000000000 +00FFFFC000000000 +01FFFF8000000000 +01FFFF0000000000 +03FFFF0000000000 +07FFFE0000000000 +0FFFFC0000000000 +1FFFF80000000000 +3FFFF00000000000 +7FFFE00000000000 +FFFFC00000000000 +FFFF800000000000 +FFFFFFFFFFFFFFF8 +FFFFFFFFFFFFFFF8 +FFFFFFFFFFFFFFF8 +FFFFFFFFFFFFFFF8 +FFFFFFFFFFFFFFF8 +FFFFFFFFFFFFFFF8 +FFFFFFFFFFFFFFF8 +FFFFFFFFFFFFFFF8 +FFFFFFFFFFFFFFF8 +FFFFFFFFFFFFFFF8 +FFFFFFFFFFFFFFF8 +FFFFFFFFFFFFFFF8 +FFFFFFFFFFFFFFF8 +ENDCHAR +STARTCHAR 005B +ENCODING 91 +SWIDTH 336 0 +DWIDTH 35 0 +BBX 27 96 8 -21 +BITMAP +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFC0000 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +ENDCHAR +STARTCHAR 005C +ENCODING 92 +SWIDTH 278 0 +DWIDTH 29 0 +BBX 29 75 0 0 +BITMAP +FFE00000 +FFE00000 +FFF00000 +7FF00000 +7FF00000 +7FF00000 +7FF80000 +7FF80000 +3FF80000 +3FF80000 +3FFC0000 +3FFC0000 +1FFC0000 +1FFC0000 +1FFC0000 +1FFE0000 +0FFE0000 +0FFE0000 +0FFE0000 +0FFF0000 +07FF0000 +07FF0000 +07FF0000 +07FF8000 +03FF8000 +03FF8000 +03FF8000 +03FFC000 +01FFC000 +01FFC000 +01FFC000 +01FFE000 +01FFE000 +00FFE000 +00FFE000 +00FFF000 +00FFF000 +007FF000 +007FF000 +007FF000 +007FF800 +003FF800 +003FF800 +003FF800 +003FFC00 +001FFC00 +001FFC00 +001FFC00 +001FFE00 +000FFE00 +000FFE00 +000FFE00 +000FFF00 +0007FF00 +0007FF00 +0007FF00 +0007FF80 +0007FF80 +0003FF80 +0003FF80 +0003FFC0 +0003FFC0 +0001FFC0 +0001FFC0 +0001FFC0 +0001FFE0 +0000FFE0 +0000FFE0 +0000FFE0 +0000FFF0 +00007FF0 +00007FF0 +00007FF0 +00007FF8 +00003FF8 +ENDCHAR +STARTCHAR 005D +ENCODING 93 +SWIDTH 336 0 +DWIDTH 35 0 +BBX 27 96 0 -21 +BITMAP +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +FFFFFFE0 +ENDCHAR +STARTCHAR 005E +ENCODING 94 +SWIDTH 585 0 +DWIDTH 61 0 +BBX 48 40 5 36 +BITMAP +00003FFC0000 +00003FFC0000 +00003FFE0000 +00007FFE0000 +00007FFF0000 +0000FFFF0000 +0000FFFF8000 +0001FFFF8000 +0001FFFFC000 +0003FFFFC000 +0003FFFFE000 +0007FFFFE000 +0007FFFFE000 +000FFFFFF000 +000FFFFFF000 +001FFFFFF800 +001FFFFFF800 +001FFE7FFC00 +003FFE7FFC00 +003FFC3FFE00 +007FFC3FFE00 +007FFC3FFF00 +00FFF81FFF00 +00FFF81FFF00 +01FFF00FFF80 +01FFF00FFF80 +03FFF00FFFC0 +03FFE007FFC0 +07FFE007FFE0 +07FFC003FFE0 +0FFFC003FFF0 +0FFF8001FFF0 +1FFF8001FFF8 +1FFF8001FFF8 +1FFF0000FFF8 +3FFF0000FFFC +3FFE00007FFC +7FFE00007FFE +7FFE00007FFE +FFFC00003FFF +ENDCHAR +STARTCHAR 005F +ENCODING 95 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 60 9 -1 -21 +BITMAP +FFFFFFFFFFFFFFF0 +FFFFFFFFFFFFFFF0 +FFFFFFFFFFFFFFF0 +FFFFFFFFFFFFFFF0 +FFFFFFFFFFFFFFF0 +FFFFFFFFFFFFFFF0 +FFFFFFFFFFFFFFF0 +FFFFFFFFFFFFFFF0 +FFFFFFFFFFFFFFF0 +ENDCHAR +STARTCHAR 0060 +ENCODING 96 +SWIDTH 336 0 +DWIDTH 35 0 +BBX 23 15 2 60 +BITMAP +FFFF00 +7FFF80 +3FFF80 +1FFFC0 +0FFFC0 +07FFE0 +03FFE0 +01FFE0 +00FFF0 +007FF0 +003FF8 +001FF8 +000FFC +0007FC +0003FE +ENDCHAR +STARTCHAR 0061 +ENCODING 97 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 51 57 3 -1 +BITMAP +00003FFF000000 +0003FFFFF80000 +000FFFFFFE0000 +003FFFFFFF8000 +007FFFFFFFC000 +00FFFFFFFFE000 +01FFFFFFFFF000 +03FFFFFFFFF800 +07FFFFFFFFF800 +07FFFFFFFFFC00 +0FFFFFFFFFFC00 +0FFFF007FFFC00 +1FFFC001FFFC00 +1FFF8000FFFE00 +3FFF8000FFFE00 +3FFF00007FFE00 +07FF00007FFE00 +000E00007FFE00 +000000007FFE00 +000000007FFE00 +00000000FFFE00 +0000000FFFFE00 +000000FFFFFE00 +00000FFFFFFE00 +0001FFFFFFFE00 +000FFFFFFFFE00 +007FFFFFFFFE00 +01FFFFFFFFFE00 +03FFFFFFFFFE00 +07FFFFFFFFFE00 +0FFFFFFFFFFE00 +1FFFFFFE7FFE00 +3FFFFFE07FFE00 +3FFFFC007FFE00 +7FFFC0007FFE00 +7FFF00007FFE00 +7FFE00007FFE00 +FFFC00007FFE00 +FFFC00007FFE00 +FFFC0000FFFE00 +FFFC0000FFFE00 +FFFC0001FFFE00 +FFFE0001FFFE00 +FFFF0007FFFE00 +FFFF800FFFFE00 +7FFFE07FFFFE00 +7FFFFFFFFFFE00 +7FFFFFFFFFFF00 +3FFFFFFFFFFF00 +3FFFFFFFFFFF00 +1FFFFFFFDFFF00 +0FFFFFFF8FFF80 +07FFFFFF0FFF80 +03FFFFFC0FFFC0 +00FFFFF00FFFC0 +003FFFC007FFE0 +0007FE00000000 +ENDCHAR +STARTCHAR 0062 +ENCODING 98 +SWIDTH 614 0 +DWIDTH 64 0 +BBX 53 76 7 -1 +BITMAP +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC007FE00000 +FFFC03FFFC0000 +FFFC0FFFFF0000 +FFFC1FFFFFC000 +FFFC7FFFFFE000 +FFFCFFFFFFF800 +FFFDFFFFFFFC00 +FFFFFFFFFFFE00 +FFFFFFFFFFFE00 +FFFFFFFFFFFF00 +FFFFFFFFFFFF80 +FFFFFE03FFFF80 +FFFFF800FFFFC0 +FFFFE0003FFFC0 +FFFFC0001FFFE0 +FFFF80000FFFE0 +FFFF80000FFFE0 +FFFF000007FFF0 +FFFE000007FFF0 +FFFE000003FFF0 +FFFE000003FFF0 +FFFE000003FFF8 +FFFC000003FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFE000001FFF8 +FFFE000003FFF0 +FFFE000003FFF0 +FFFE000003FFF0 +FFFF000007FFF0 +FFFF000007FFF0 +FFFF80000FFFE0 +FFFFC0000FFFE0 +FFFFE0001FFFE0 +FFFFF0003FFFC0 +FFFFF800FFFFC0 +FFFFFF03FFFF80 +FFFFFFFFFFFF80 +FFFFFFFFFFFF00 +FFFFFFFFFFFE00 +FFFDFFFFFFFC00 +FFFCFFFFFFFC00 +FFFC7FFFFFF800 +FFFC3FFFFFE000 +FFFC1FFFFFC000 +FFFC07FFFF8000 +FFFC01FFFC0000 +0000003FE00000 +ENDCHAR +STARTCHAR 0063 +ENCODING 99 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 50 57 4 -1 +BITMAP +00000FFF000000 +0000FFFFF00000 +0003FFFFFC0000 +000FFFFFFF0000 +003FFFFFFF8000 +007FFFFFFFC000 +00FFFFFFFFE000 +01FFFFFFFFF000 +03FFFFFFFFF800 +07FFFFFFFFFC00 +07FFFFFFFFFC00 +0FFFFC07FFFE00 +1FFFF001FFFE00 +1FFFC000FFFF00 +3FFF80007FFF00 +3FFF80003FFF80 +3FFF00003FFF80 +7FFF00001FFC00 +7FFE00001E0000 +7FFE0000000000 +7FFE0000000000 +7FFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +7FFE0000000000 +7FFE00000F0000 +7FFE00000FFE00 +7FFE00001FFFC0 +7FFF00001FFFC0 +3FFF00001FFF80 +3FFF80003FFF80 +3FFFC0007FFF80 +1FFFE0007FFF00 +1FFFF001FFFF00 +0FFFFC07FFFE00 +07FFFFFFFFFE00 +07FFFFFFFFFC00 +03FFFFFFFFF800 +01FFFFFFFFF800 +00FFFFFFFFF000 +007FFFFFFFE000 +003FFFFFFF8000 +000FFFFFFF0000 +0003FFFFFC0000 +0000FFFFF00000 +00000FFF000000 +ENDCHAR +STARTCHAR 0064 +ENCODING 100 +SWIDTH 614 0 +DWIDTH 64 0 +BBX 53 76 4 -1 +BITMAP +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +00003FF001FFF8 +0001FFFE01FFF8 +0007FFFF81FFF8 +001FFFFFC1FFF8 +007FFFFFF1FFF8 +00FFFFFFF9FFF8 +01FFFFFFFDFFF8 +03FFFFFFFFFFF8 +07FFFFFFFFFFF8 +07FFFFFFFFFFF8 +0FFFFFFFFFFFF8 +0FFFFE03FFFFF8 +1FFFF800FFFFF8 +1FFFE0003FFFF8 +3FFFC0001FFFF8 +3FFF80000FFFF8 +7FFF80000FFFF8 +7FFF000007FFF8 +7FFF000007FFF8 +7FFE000003FFF8 +7FFE000003FFF8 +FFFE000003FFF8 +FFFC000003FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +7FFE000003FFF8 +7FFE000003FFF8 +7FFE000003FFF8 +7FFF000007FFF8 +7FFF000007FFF8 +3FFF80000FFFF8 +3FFF80000FFFF8 +3FFFC0001FFFF8 +1FFFE0003FFFF8 +1FFFF800FFFFF8 +0FFFFE03FFFFF8 +0FFFFFFFFFFFF8 +07FFFFFFFFFFF8 +03FFFFFFFFFFF8 +01FFFFFFFDFFF8 +01FFFFFFF9FFF8 +00FFFFFFF1FFF8 +003FFFFFE1FFF8 +001FFFFFC1FFF8 +0007FFFF01FFF8 +0001FFFC01FFF8 +00003FE0000000 +ENDCHAR +STARTCHAR 0065 +ENCODING 101 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 51 57 3 -1 +BITMAP +00000FFE000000 +0000FFFFC00000 +0003FFFFF80000 +000FFFFFFE0000 +001FFFFFFF0000 +007FFFFFFFC000 +00FFFFFFFFE000 +01FFFFFFFFF000 +03FFFFFFFFF800 +03FFFFFFFFF800 +07FFFFFFFFFC00 +0FFFFC07FFFE00 +0FFFF001FFFE00 +1FFFE0007FFF00 +1FFF80003FFF00 +3FFF80001FFF80 +3FFF00001FFF80 +3FFE00000FFF80 +7FFE00000FFF80 +7FFE00000FFFC0 +7FFE000007FFC0 +7FFC000007FFC0 +FFFC000007FFC0 +FFFC000007FFC0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFFFFFFFFFFE0 +FFFC0000000000 +FFFC0000000000 +7FFC0000000000 +7FFC0000000000 +7FFE0000000000 +7FFE0000000000 +7FFE00000F0000 +3FFF00001FFE00 +3FFF80001FFFC0 +3FFFC0003FFF80 +1FFFE0007FFF80 +1FFFF000FFFF80 +0FFFFE03FFFF00 +07FFFFFFFFFE00 +07FFFFFFFFFE00 +03FFFFFFFFFC00 +01FFFFFFFFF800 +00FFFFFFFFF000 +007FFFFFFFE000 +003FFFFFFFC000 +000FFFFFFF0000 +0003FFFFFE0000 +0000FFFFF00000 +00000FFF000000 +ENDCHAR +STARTCHAR 0066 +ENCODING 102 +SWIDTH 336 0 +DWIDTH 35 0 +BBX 35 76 2 0 +BITMAP +00003FF800 +0001FFFFC0 +0007FFFFE0 +001FFFFFE0 +003FFFFFE0 +007FFFFFC0 +007FFFFFC0 +00FFFFFFC0 +00FFFFFFC0 +00FFFFFFC0 +01FFFFFFC0 +01FFFF00C0 +01FFFC0000 +01FFFC0000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +FFFFFFFE00 +FFFFFFFE00 +FFFFFFFE00 +FFFFFFFE00 +FFFFFFFE00 +FFFFFFFE00 +FFFFFFFE00 +FFFFFFFE00 +FFFFFFFE00 +FFFFFFFE00 +FFFFFFFE00 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +01FFF80000 +ENDCHAR +STARTCHAR 0067 +ENCODING 103 +SWIDTH 614 0 +DWIDTH 64 0 +BBX 53 78 4 -22 +BITMAP +00003FE0000000 +0003FFFC01FFF8 +000FFFFF01FFF8 +001FFFFFC1FFF8 +007FFFFFE1FFF8 +00FFFFFFF1FFF8 +01FFFFFFF9FFF8 +03FFFFFFFDFFF8 +07FFFFFFFFFFF8 +07FFFFFFFFFFF8 +0FFFFFFFFFFFF8 +0FFFFE03FFFFF8 +1FFFF800FFFFF8 +1FFFE0003FFFF8 +3FFFC0001FFFF8 +3FFF80000FFFF8 +7FFF80000FFFF8 +7FFF000007FFF8 +7FFF000007FFF8 +7FFE000003FFF8 +7FFE000003FFF8 +FFFE000003FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000003FFF8 +FFFE000003FFF8 +7FFE000003FFF8 +7FFE000003FFF8 +7FFE000007FFF8 +7FFF000007FFF8 +3FFF00000FFFF8 +3FFF80001FFFF8 +3FFFC0001FFFF8 +1FFFE0007FFFF8 +1FFFF000FFFFF8 +0FFFFE07FFFFF8 +0FFFFFFFFFFFF8 +07FFFFFFFFFFF8 +07FFFFFFFDFFF8 +03FFFFFFF9FFF8 +01FFFFFFF1FFF8 +00FFFFFFE1FFF8 +007FFFFFC1FFF8 +003FFFFF81FFF8 +000FFFFE01FFF8 +0003FFF801FFF8 +00007FC001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF0 +3C00000001FFF0 +3FFE000003FFF0 +3FFFE00003FFF0 +3FFFE00007FFF0 +3FFFF0000FFFE0 +3FFFF8001FFFE0 +1FFFFE00FFFFE0 +1FFFFFFFFFFFC0 +0FFFFFFFFFFFC0 +0FFFFFFFFFFF80 +07FFFFFFFFFF00 +03FFFFFFFFFF00 +01FFFFFFFFFE00 +00FFFFFFFFF800 +007FFFFFFFF000 +001FFFFFFFC000 +0003FFFFFE0000 +00001FFFE00000 +ENDCHAR +STARTCHAR 0068 +ENCODING 104 +SWIDTH 614 0 +DWIDTH 64 0 +BBX 50 75 7 0 +BITMAP +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC001FF00000 +FFFC01FFFE0000 +FFFC07FFFF8000 +FFFC0FFFFFE000 +FFFC3FFFFFF000 +FFFC7FFFFFF800 +FFFCFFFFFFFC00 +FFFDFFFFFFFE00 +FFFFFFFFFFFF00 +FFFFFFFFFFFF00 +FFFFFFFFFFFF00 +FFFFFE03FFFF80 +FFFFF000FFFF80 +FFFFE0007FFF80 +FFFFC0003FFF80 +FFFF80001FFFC0 +FFFF00001FFFC0 +FFFF00001FFFC0 +FFFE00000FFFC0 +FFFE00000FFFC0 +FFFE00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +ENDCHAR +STARTCHAR 0069 +ENCODING 105 +SWIDTH 278 0 +DWIDTH 29 0 +BBX 14 75 7 0 +BITMAP +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +0000 +0000 +0000 +0000 +0000 +0000 +0000 +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +ENDCHAR +STARTCHAR 006A +ENCODING 106 +SWIDTH 278 0 +DWIDTH 29 0 +BBX 27 97 -5 -22 +BITMAP +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +00000000 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +0007FFE0 +000FFFE0 +000FFFE0 +001FFFE0 +007FFFC0 +7FFFFFC0 +7FFFFFC0 +7FFFFFC0 +7FFFFFC0 +7FFFFF80 +7FFFFF80 +7FFFFF00 +FFFFFF00 +FFFFFE00 +FFFFFC00 +FFFFF000 +FFFFE000 +07FE0000 +ENDCHAR +STARTCHAR 006B +ENCODING 107 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 49 75 7 0 +BITMAP +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0001FFFF00 +FFFC0003FFFE00 +FFFC0007FFFC00 +FFFC000FFFF800 +FFFC001FFFF000 +FFFC001FFFE000 +FFFC003FFFE000 +FFFC007FFFC000 +FFFC00FFFF8000 +FFFC01FFFF0000 +FFFC03FFFE0000 +FFFC07FFFC0000 +FFFC0FFFF80000 +FFFC1FFFF00000 +FFFC3FFFE00000 +FFFC7FFFC00000 +FFFC7FFF800000 +FFFCFFFF000000 +FFFDFFFE000000 +FFFFFFFE000000 +FFFFFFFC000000 +FFFFFFFE000000 +FFFFFFFE000000 +FFFFFFFF000000 +FFFFFFFF800000 +FFFFFFFF800000 +FFFFFFFFC00000 +FFFFFFFFC00000 +FFFFFFFFE00000 +FFFFFFFFE00000 +FFFFF7FFF00000 +FFFFE3FFF00000 +FFFFE3FFF80000 +FFFFC1FFFC0000 +FFFF81FFFC0000 +FFFF00FFFE0000 +FFFE007FFE0000 +FFFC007FFF0000 +FFFC003FFF0000 +FFFC003FFF8000 +FFFC001FFF8000 +FFFC000FFFC000 +FFFC000FFFE000 +FFFC0007FFE000 +FFFC0007FFF000 +FFFC0003FFF000 +FFFC0003FFF800 +FFFC0001FFF800 +FFFC0000FFFC00 +FFFC0000FFFC00 +FFFC00007FFE00 +FFFC00007FFF00 +FFFC00003FFF00 +FFFC00001FFF80 +FFFC00001FFF80 +ENDCHAR +STARTCHAR 006C +ENCODING 108 +SWIDTH 278 0 +DWIDTH 29 0 +BBX 14 75 7 0 +BITMAP +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +FFFC +ENDCHAR +STARTCHAR 006D +ENCODING 109 +SWIDTH 883 0 +DWIDTH 92 0 +BBX 78 56 6 0 +BITMAP +0000003FC00000FF8000 +FFFC01FFF80007FFF800 +FFFC07FFFE001FFFFE00 +FFFC1FFFFF003FFFFF00 +FFFC3FFFFF80FFFFFF80 +FFFC7FFFFFC1FFFFFFC0 +FFFCFFFFFFE3FFFFFFE0 +FFFDFFFFFFF7FFFFFFE0 +FFFFFFFFFFFFFFFFFFF0 +FFFFFFFFFFFFFFFFFFF0 +FFFFFFFFFFFFFFFFFFF8 +FFFFF80FFFFFFC1FFFF8 +FFFFE007FFFFE007FFF8 +FFFFC003FFFFC003FFFC +FFFF8001FFFF8001FFFC +FFFF0001FFFF0001FFFC +FFFF0001FFFF0001FFFC +FFFE0000FFFE0000FFFC +FFFE0000FFFE0000FFFC +FFFE0000FFFE0000FFFC +FFFE0000FFFE0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +FFFC0000FFFC0000FFFC +ENDCHAR +STARTCHAR 006E +ENCODING 110 +SWIDTH 614 0 +DWIDTH 64 0 +BBX 50 56 7 0 +BITMAP +0000001FF80000 +FFFC00FFFF0000 +FFFC07FFFFC000 +FFFC0FFFFFF000 +FFFC3FFFFFF800 +FFFC7FFFFFFC00 +FFFCFFFFFFFE00 +FFFDFFFFFFFE00 +FFFFFFFFFFFF00 +FFFFFFFFFFFF00 +FFFFFFFFFFFF80 +FFFFFE03FFFF80 +FFFFF000FFFF80 +FFFFE0007FFF80 +FFFFC0003FFFC0 +FFFF80001FFFC0 +FFFF00001FFFC0 +FFFF00001FFFC0 +FFFE00001FFFC0 +FFFE00000FFFC0 +FFFE00000FFFC0 +FFFE00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +ENDCHAR +STARTCHAR 006F +ENCODING 111 +SWIDTH 614 0 +DWIDTH 64 0 +BBX 56 57 4 -1 +BITMAP +000003FFC00000 +00003FFFFC0000 +0000FFFFFF0000 +0003FFFFFFC000 +000FFFFFFFF000 +003FFFFFFFF800 +007FFFFFFFFC00 +00FFFFFFFFFF00 +01FFFFFFFFFF80 +03FFFFFFFFFF80 +03FFFFFFFFFFC0 +07FFFF00FFFFE0 +0FFFFC003FFFF0 +0FFFF0000FFFF0 +1FFFE00007FFF8 +1FFFC00003FFF8 +3FFF800001FFFC +3FFF800001FFFC +7FFF000000FFFC +7FFF000000FFFE +7FFE0000007FFE +7FFE0000007FFE +FFFE0000007FFF +FFFC0000003FFF +FFFC0000003FFF +FFFC0000003FFF +FFFC0000003FFF +FFFC0000003FFF +FFFC0000003FFF +FFFC0000003FFF +FFFC0000003FFF +FFFC0000003FFF +FFFC0000003FFF +FFFC0000003FFF +7FFE0000007FFE +7FFE0000007FFE +7FFE0000007FFE +7FFF000000FFFE +7FFF000000FFFC +3FFF800001FFFC +3FFF800001FFFC +3FFFC00003FFF8 +1FFFE00007FFF8 +1FFFF0000FFFF0 +0FFFFC003FFFF0 +07FFFF00FFFFE0 +07FFFFFFFFFFC0 +03FFFFFFFFFF80 +01FFFFFFFFFF00 +00FFFFFFFFFE00 +007FFFFFFFFC00 +003FFFFFFFF800 +000FFFFFFFF000 +0003FFFFFFC000 +0000FFFFFF0000 +00003FFFFC0000 +000003FFC00000 +ENDCHAR +STARTCHAR 0070 +ENCODING 112 +SWIDTH 614 0 +DWIDTH 64 0 +BBX 53 77 7 -21 +BITMAP +0000003FE00000 +FFFC01FFFC0000 +FFFC07FFFF0000 +FFFC1FFFFFC000 +FFFC3FFFFFE000 +FFFC7FFFFFF800 +FFFCFFFFFFFC00 +FFFDFFFFFFFE00 +FFFFFFFFFFFE00 +FFFFFFFFFFFF00 +FFFFFFFFFFFF80 +FFFFFE03FFFF80 +FFFFF800FFFFC0 +FFFFE0003FFFC0 +FFFFC0001FFFE0 +FFFF80000FFFE0 +FFFF80000FFFE0 +FFFF000007FFF0 +FFFF000007FFF0 +FFFE000003FFF0 +FFFE000003FFF0 +FFFE000003FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFE000001FFF8 +FFFE000003FFF0 +FFFE000003FFF0 +FFFE000003FFF0 +FFFF000007FFF0 +FFFF000007FFF0 +FFFF80000FFFE0 +FFFFC0000FFFE0 +FFFFE0001FFFE0 +FFFFF0003FFFC0 +FFFFF8007FFFC0 +FFFFFF03FFFF80 +FFFFFFFFFFFF00 +FFFFFFFFFFFF00 +FFFFFFFFFFFE00 +FFFFFFFFFFFC00 +FFFDFFFFFFF800 +FFFCFFFFFFF000 +FFFC3FFFFFE000 +FFFC1FFFFFC000 +FFFC0FFFFF0000 +FFFC03FFFC0000 +FFFC007FE00000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +FFFC0000000000 +ENDCHAR +STARTCHAR 0071 +ENCODING 113 +SWIDTH 614 0 +DWIDTH 64 0 +BBX 53 77 4 -21 +BITMAP +00003FE0000000 +0001FFFE01FFF8 +0007FFFF81FFF8 +001FFFFFC1FFF8 +003FFFFFE1FFF8 +00FFFFFFF1FFF8 +01FFFFFFF9FFF8 +03FFFFFFFDFFF8 +03FFFFFFFFFFF8 +07FFFFFFFFFFF8 +0FFFFFFFFFFFF8 +0FFFFE03FFFFF8 +1FFFF800FFFFF8 +1FFFE0003FFFF8 +3FFFC0001FFFF8 +3FFF80000FFFF8 +3FFF80000FFFF8 +7FFF000007FFF8 +7FFF000007FFF8 +7FFE000003FFF8 +7FFE000003FFF8 +FFFE000003FFF8 +FFFE000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000003FFF8 +7FFE000003FFF8 +7FFE000003FFF8 +7FFE000007FFF8 +7FFE000007FFF8 +7FFF00000FFFF8 +3FFF00000FFFF8 +3FFF80001FFFF8 +1FFFC0003FFFF8 +1FFFE0007FFFF8 +1FFFF000FFFFF8 +0FFFFE07FFFFF8 +07FFFFFFFFFFF8 +07FFFFFFFFFFF8 +03FFFFFFFFFFF8 +01FFFFFFFFFFF8 +00FFFFFFFDFFF8 +007FFFFFF9FFF8 +003FFFFFF1FFF8 +001FFFFFC1FFF8 +0007FFFF81FFF8 +0001FFFE01FFF8 +00003FE001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +0000000001FFF8 +ENDCHAR +STARTCHAR 0072 +ENCODING 114 +SWIDTH 384 0 +DWIDTH 40 0 +BBX 34 56 7 0 +BITMAP +000003F800 +FFFC0FFE00 +FFFC1FFF80 +FFFC3FFFC0 +FFFC7FFFC0 +FFFCFFFF80 +FFFDFFFF80 +FFFDFFFF80 +FFFFFFFF80 +FFFFFFFF00 +FFFFFFFF00 +FFFFFFFF00 +FFFFFFFF00 +FFFFFFFE00 +FFFFF81E00 +FFFFE00600 +FFFFC00000 +FFFF800000 +FFFF000000 +FFFF000000 +FFFF000000 +FFFE000000 +FFFE000000 +FFFE000000 +FFFE000000 +FFFE000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +FFFC000000 +ENDCHAR +STARTCHAR 0073 +ENCODING 115 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 51 57 2 -1 +BITMAP +00003FFF000000 +0003FFFFF00000 +001FFFFFFE0000 +007FFFFFFF8000 +00FFFFFFFFC000 +01FFFFFFFFE000 +03FFFFFFFFF000 +07FFFFFFFFF800 +0FFFFFFFFFFC00 +0FFFFFFFFFFC00 +1FFFFFFFFFFE00 +1FFFF007FFFE00 +1FFFC001FFFF00 +3FFF80007FFF00 +3FFF00007FFF80 +3FFF00003FFF80 +3FFF00001FFC00 +3FFF80001E0000 +3FFFE000000000 +3FFFF800000000 +3FFFFF80000000 +1FFFFFF8000000 +1FFFFFFF800000 +0FFFFFFFF80000 +0FFFFFFFFF0000 +07FFFFFFFFC000 +03FFFFFFFFF000 +01FFFFFFFFFC00 +00FFFFFFFFFE00 +003FFFFFFFFF00 +000FFFFFFFFF80 +0003FFFFFFFF80 +00007FFFFFFFC0 +000007FFFFFFC0 +0000007FFFFFC0 +00000007FFFFE0 +000000007FFFE0 +000000000FFFE0 +003C000007FFE0 +1FFC000007FFE0 +FFFE000007FFE0 +FFFE000007FFE0 +7FFF00000FFFE0 +7FFF80000FFFC0 +3FFFE0003FFFC0 +3FFFF801FFFFC0 +1FFFFFFFFFFF80 +1FFFFFFFFFFF00 +0FFFFFFFFFFF00 +07FFFFFFFFFE00 +03FFFFFFFFFC00 +01FFFFFFFFF800 +007FFFFFFFF000 +003FFFFFFFC000 +000FFFFFFF0000 +0001FFFFFC0000 +00001FFF800000 +ENDCHAR +STARTCHAR 0074 +ENCODING 116 +SWIDTH 336 0 +DWIDTH 35 0 +BBX 32 74 2 -1 +BITMAP +00000800 +00003800 +00007800 +0001F800 +0007F800 +001FF800 +003FF800 +00FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +FFFFFFFE +FFFFFFFE +FFFFFFFE +FFFFFFFE +FFFFFFFE +FFFFFFFE +FFFFFFFE +FFFFFFFE +FFFFFFFE +FFFFFFFE +FFFFFFFE +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFF800 +01FFFC00 +01FFFE0E +01FFFFFE +00FFFFFE +00FFFFFE +00FFFFFE +00FFFFFE +007FFFFE +003FFFFF +001FFFFF +000FFFFF +0003FFFE +0000FFE0 +ENDCHAR +STARTCHAR 0075 +ENCODING 117 +SWIDTH 614 0 +DWIDTH 64 0 +BBX 50 56 7 -1 +BITMAP +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00000FFFC0 +FFFC00001FFFC0 +FFFC00001FFFC0 +FFFC00001FFFC0 +FFFE00001FFFC0 +FFFE00003FFFC0 +FFFE00007FFFC0 +FFFF0000FFFFC0 +7FFF8001FFFFC0 +7FFFC003FFFFC0 +7FFFF01FFFFFC0 +7FFFFFFFFFFFC0 +3FFFFFFFFFFFC0 +3FFFFFFFFFFFC0 +1FFFFFFFEFFFC0 +1FFFFFFFCFFFC0 +0FFFFFFF8FFFC0 +07FFFFFF0FFFC0 +01FFFFFC0FFFC0 +00FFFFF00FFFC0 +003FFFC00FFFC0 +0007FE00000000 +ENDCHAR +STARTCHAR 0076 +ENCODING 118 +SWIDTH 537 0 +DWIDTH 56 0 +BBX 53 55 1 0 +BITMAP +FFFC000001FFF8 +FFFC000001FFF8 +FFFC000001FFF8 +7FFE000003FFF0 +7FFE000003FFF0 +3FFE000007FFE0 +3FFF000007FFE0 +3FFF000007FFE0 +1FFF80000FFFC0 +1FFF80000FFFC0 +0FFF80000FFFC0 +0FFFC0001FFF80 +0FFFC0001FFF80 +07FFC0001FFF00 +07FFE0003FFF00 +07FFE0003FFF00 +03FFE0003FFE00 +03FFF0007FFE00 +01FFF0007FFE00 +01FFF000FFFC00 +01FFF800FFFC00 +00FFF800FFF800 +00FFFC01FFF800 +00FFFC01FFF800 +007FFC01FFF000 +007FFE03FFF000 +003FFE03FFF000 +003FFE03FFE000 +003FFF07FFE000 +001FFF07FFC000 +001FFF07FFC000 +000FFF8FFFC000 +000FFF8FFF8000 +000FFF8FFF8000 +0007FFDFFF8000 +0007FFDFFF0000 +0007FFDFFF0000 +0003FFFFFE0000 +0003FFFFFE0000 +0001FFFFFE0000 +0001FFFFFC0000 +0001FFFFFC0000 +0000FFFFFC0000 +0000FFFFF80000 +0000FFFFF80000 +00007FFFF00000 +00007FFFF00000 +00003FFFF00000 +00003FFFE00000 +00003FFFE00000 +00001FFFE00000 +00001FFFC00000 +00000FFFC00000 +00000FFF800000 +00000FFF800000 +ENDCHAR +STARTCHAR 0077 +ENCODING 119 +SWIDTH 806 0 +DWIDTH 84 0 +BBX 83 55 0 0 +BITMAP +FFFC00003FFF800007FFE0 +FFFE00003FFF80000FFFE0 +7FFE00003FFFC0000FFFC0 +7FFE00007FFFC0000FFFC0 +7FFE00007FFFC0000FFFC0 +3FFF00007FFFC0001FFF80 +3FFF00007FFFE0001FFF80 +3FFF0000FFFFE0001FFF80 +1FFF8000FFFFE0003FFF00 +1FFF8000FFFFE0003FFF00 +1FFF8001FFFFF0003FFF00 +0FFF8001FFFFF0003FFE00 +0FFFC001FFFFF0007FFE00 +0FFFC001FFFFF8007FFE00 +07FFC003FFFFF8007FFC00 +07FFE003FFFFF800FFFC00 +07FFE003FFFFF800FFFC00 +03FFE003FFFFFC00FFF800 +03FFE007FFFFFC00FFF800 +03FFF007FFFFFC01FFF800 +01FFF007FFBFFC01FFF800 +01FFF00FFFBFFE01FFF000 +01FFF80FFFBFFE03FFF000 +01FFF80FFF1FFE03FFF000 +00FFF80FFF1FFE03FFE000 +00FFF81FFF1FFF03FFE000 +00FFFC1FFF1FFF07FFE000 +007FFC1FFE0FFF07FFC000 +007FFC1FFE0FFF07FFC000 +007FFE3FFE0FFF8FFFC000 +003FFE3FFE07FF8FFF8000 +003FFE3FFC07FF8FFF8000 +003FFE7FFC07FFCFFF8000 +001FFF7FFC07FFDFFF0000 +001FFF7FF803FFDFFF0000 +001FFF7FF803FFDFFF0000 +000FFFFFF803FFFFFE0000 +000FFFFFF801FFFFFE0000 +000FFFFFF001FFFFFE0000 +0007FFFFF001FFFFFE0000 +0007FFFFF001FFFFFC0000 +0007FFFFF000FFFFFC0000 +0007FFFFE000FFFFFC0000 +0003FFFFE000FFFFF80000 +0003FFFFE000FFFFF80000 +0003FFFFC0007FFFF80000 +0001FFFFC0007FFFF00000 +0001FFFFC0007FFFF00000 +0001FFFFC0003FFFF00000 +0000FFFF80003FFFE00000 +0000FFFF80003FFFE00000 +0000FFFF80003FFFE00000 +00007FFF80001FFFC00000 +00007FFF00001FFFC00000 +00007FFF00001FFFC00000 +ENDCHAR +STARTCHAR 0078 +ENCODING 120 +SWIDTH 556 0 +DWIDTH 58 0 +BBX 54 55 2 0 +BITMAP +3FFFC0000FFFF0 +3FFFE0001FFFF0 +1FFFE0003FFFE0 +0FFFF0003FFFC0 +0FFFF8007FFFC0 +07FFF8007FFF80 +03FFFC00FFFF00 +03FFFC01FFFE00 +01FFFE01FFFE00 +00FFFE03FFFC00 +00FFFF07FFF800 +007FFF87FFF800 +007FFF8FFFF000 +003FFFCFFFE000 +001FFFDFFFE000 +001FFFFFFFC000 +000FFFFFFF8000 +0007FFFFFF8000 +0007FFFFFF0000 +0003FFFFFE0000 +0001FFFFFE0000 +0001FFFFFC0000 +0000FFFFF80000 +0000FFFFF80000 +00007FFFF00000 +00003FFFE00000 +00003FFFE00000 +00003FFFF00000 +00007FFFF80000 +00007FFFF80000 +0000FFFFFC0000 +0001FFFFFE0000 +0001FFFFFE0000 +0003FFFFFF0000 +0007FFFFFF8000 +0007FFFFFF8000 +000FFFFFFFC000 +001FFFFFFFE000 +001FFFDFFFE000 +003FFFCFFFF000 +007FFF8FFFF800 +007FFF07FFF800 +00FFFF03FFFC00 +01FFFE03FFFE00 +01FFFE01FFFE00 +03FFFC00FFFF00 +07FFF800FFFF80 +07FFF8007FFF80 +0FFFF0003FFFC0 +1FFFE0003FFFE0 +3FFFE0001FFFE0 +3FFFC0000FFFF0 +7FFFC0000FFFF8 +FFFF800007FFF8 +FFFF000003FFFC +ENDCHAR +STARTCHAR 0079 +ENCODING 121 +SWIDTH 528 0 +DWIDTH 55 0 +BBX 53 77 1 -22 +BITMAP +FFFC000001FFF8 +7FFC000003FFF0 +7FFE000003FFF0 +7FFE000003FFF0 +3FFE000003FFE0 +3FFF000007FFE0 +3FFF000007FFE0 +1FFF000007FFC0 +1FFF80000FFFC0 +1FFF80000FFFC0 +0FFF80000FFF80 +0FFFC0001FFF80 +0FFFC0001FFF80 +07FFC0001FFF00 +07FFE0003FFF00 +07FFE0003FFF00 +03FFE0003FFE00 +03FFF0007FFE00 +01FFF0007FFE00 +01FFF0007FFC00 +01FFF800FFFC00 +00FFF800FFFC00 +00FFF800FFF800 +00FFFC01FFF800 +007FFC01FFF800 +007FFC01FFF000 +007FFE03FFF000 +003FFE03FFE000 +003FFE03FFE000 +003FFE07FFE000 +001FFF07FFC000 +001FFF07FFC000 +001FFF07FFC000 +000FFF8FFF8000 +000FFF8FFF8000 +000FFF8FFF8000 +0007FFDFFF0000 +0007FFDFFF0000 +0003FFDFFF0000 +0003FFFFFE0000 +0003FFFFFE0000 +0001FFFFFE0000 +0001FFFFFC0000 +0001FFFFFC0000 +0000FFFFFC0000 +0000FFFFF80000 +0000FFFFF80000 +00007FFFF80000 +00007FFFF00000 +00007FFFF00000 +00003FFFF00000 +00003FFFE00000 +00003FFFE00000 +00001FFFC00000 +00001FFFC00000 +00001FFFC00000 +00001FFF800000 +00001FFF800000 +00003FFF800000 +00003FFF000000 +00007FFF000000 +00007FFF000000 +0000FFFE000000 +0000FFFE000000 +0001FFFE000000 +0807FFFC000000 +0FFFFFFC000000 +0FFFFFF8000000 +0FFFFFF8000000 +0FFFFFF0000000 +0FFFFFE0000000 +07FFFFE0000000 +07FFFFC0000000 +07FFFF80000000 +07FFFE00000000 +07FFF800000000 +01FFC000000000 +ENDCHAR +STARTCHAR 007A +ENCODING 122 +SWIDTH 499 0 +DWIDTH 52 0 +BBX 48 55 2 0 +BITMAP +3FFFFFFFFFFC +3FFFFFFFFFFC +3FFFFFFFFFFC +3FFFFFFFFFFC +3FFFFFFFFFFC +3FFFFFFFFFFC +3FFFFFFFFFFC +3FFFFFFFFFFC +3FFFFFFFFFFC +3FFFFFFFFFFC +3FFFFFFFFFFC +0000000FFFF8 +0000001FFFF0 +0000003FFFE0 +0000007FFFC0 +000000FFFFC0 +000001FFFF80 +000003FFFF00 +000003FFFE00 +000007FFFC00 +00000FFFFC00 +00001FFFF800 +00003FFFF000 +00007FFFE000 +00007FFFC000 +0000FFFF8000 +0001FFFF8000 +0003FFFF0000 +0007FFFE0000 +0007FFFC0000 +000FFFF80000 +001FFFF80000 +003FFFF00000 +007FFFE00000 +007FFFC00000 +00FFFF800000 +01FFFF000000 +03FFFF000000 +07FFFE000000 +0FFFFC000000 +0FFFF8000000 +1FFFF0000000 +3FFFE0000000 +7FFFC0000000 +FFFFFFFFFFFF +FFFFFFFFFFFF +FFFFFFFFFFFF +FFFFFFFFFFFF +FFFFFFFFFFFF +FFFFFFFFFFFF +FFFFFFFFFFFF +FFFFFFFFFFFF +FFFFFFFFFFFF +FFFFFFFFFFFF +FFFFFFFFFFFF +ENDCHAR +STARTCHAR 007B +ENCODING 123 +SWIDTH 384 0 +DWIDTH 40 0 +BBX 34 98 3 -22 +BITMAP +000001FFC0 +00000FFFC0 +00007FFFC0 +0000FFFFC0 +0003FFFFC0 +0007FFFFC0 +0007FFFFC0 +000FFFFFC0 +000FFFFFC0 +001FFFFFC0 +001FFFFFC0 +001FFFFFC0 +001FFFFFC0 +003FFFE000 +003FFF8000 +003FFF0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +007FFE0000 +007FFE0000 +007FFE0000 +007FFC0000 +00FFFC0000 +00FFFC0000 +01FFFC0000 +03FFF80000 +1FFFF80000 +FFFFF00000 +FFFFF00000 +FFFFE00000 +FFFFC00000 +FFFF800000 +FFFE000000 +FFFC000000 +FFFE000000 +FFFF800000 +FFFFC00000 +FFFFE00000 +FFFFE00000 +FFFFF00000 +1FFFF80000 +07FFF80000 +01FFF80000 +01FFFC0000 +00FFFC0000 +00FFFC0000 +007FFC0000 +007FFE0000 +007FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFE0000 +003FFF0000 +003FFF8000 +003FFFE000 +001FFFFFC0 +001FFFFFC0 +001FFFFFC0 +001FFFFFC0 +000FFFFFC0 +000FFFFFC0 +0007FFFFC0 +0003FFFFC0 +0001FFFFC0 +0000FFFFC0 +00007FFFC0 +00001FFFC0 +000001FFC0 +ENDCHAR +STARTCHAR 007C +ENCODING 124 +SWIDTH 278 0 +DWIDTH 29 0 +BBX 11 98 9 -23 +BITMAP +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +FFE0 +ENDCHAR +STARTCHAR 007D +ENCODING 125 +SWIDTH 384 0 +DWIDTH 40 0 +BBX 34 98 3 -22 +BITMAP +FFE0000000 +FFFE000000 +FFFF800000 +FFFFC00000 +FFFFF00000 +FFFFF00000 +FFFFF80000 +FFFFFC0000 +FFFFFC0000 +FFFFFE0000 +FFFFFE0000 +FFFFFE0000 +FFFFFE0000 +01FFFF0000 +007FFF0000 +003FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF8000 +000FFF8000 +000FFF8000 +000FFFC000 +000FFFC000 +000FFFE000 +0007FFF000 +0007FFFE00 +0003FFFFC0 +0003FFFFC0 +0001FFFFC0 +0000FFFFC0 +00007FFFC0 +00001FFFC0 +00000FFFC0 +00001FFFC0 +00007FFFC0 +0000FFFFC0 +0001FFFFC0 +0001FFFFC0 +0003FFFFC0 +0007FFFE00 +0007FFF000 +000FFFE000 +000FFFE000 +000FFFC000 +000FFF8000 +001FFF8000 +001FFF8000 +001FFF8000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +001FFF0000 +003FFF0000 +007FFF0000 +01FFFF0000 +FFFFFE0000 +FFFFFE0000 +FFFFFE0000 +FFFFFE0000 +FFFFFC0000 +FFFFFC0000 +FFFFF80000 +FFFFF80000 +FFFFF00000 +FFFFC00000 +FFFF800000 +FFFC000000 +FFE0000000 +ENDCHAR +STARTCHAR 007E +ENCODING 126 +SWIDTH 585 0 +DWIDTH 61 0 +BBX 54 20 3 26 +BITMAP +001FF000000004 +00FFFF0000000C +03FFFFC000001C +0FFFFFF800003C +1FFFFFFE0000FC +7FFFFFFFC003FC +FFFFFFFFF80FFC +FFFFFFFFFFFFFC +FFFFFFFFFFFFFC +FFFFFFFFFFFFFC +FFFFFFFFFFFFFC +FFFFFFFFFFFFFC +FFFFFFFFFFFFFC +FFC03FFFFFFFFC +FE0007FFFFFFF0 +FC0000FFFFFFE0 +F000003FFFFFC0 +E0000007FFFF00 +C0000001FFFC00 +800000003FE000 +ENDCHAR +STARTCHAR 00A0 +ENCODING 160 +SWIDTH 268 0 +DWIDTH 28 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +ENDFONT diff --git a/gui/themes/fonts/ArialBold.bdf b/gui/themes/fonts/ArialBold.bdf new file mode 100644 index 0000000000..65869e0e7b --- /dev/null +++ b/gui/themes/fonts/ArialBold.bdf @@ -0,0 +1,1538 @@ +STARTFONT 2.1 +COMMENT +COMMENT Converted from TrueType font "arialbd.ttf" by "ttf2bdf 2.8". +COMMENT +FONT -FreeType-Arial-Bold-R-Normal--12-120-75-75-P-62-ISO10646-1 +SIZE 12 75 75 +FONTBOUNDINGBOX 14 14 -1 -3 +STARTPROPERTIES 19 +FOUNDRY "FreeType" +FAMILY_NAME "Arial" +WEIGHT_NAME "Bold" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 12 +POINT_SIZE 120 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "P" +AVERAGE_WIDTH 62 +CHARSET_REGISTRY "ISO10646" +CHARSET_ENCODING "1" +FONT_ASCENT 11 +FONT_DESCENT 2 +COPYRIGHT "Typeface © The Monotype Corporation plc. Data © The Monotype Corporation plc/Type Solutions Inc. 1990-1992. All Rights Reserved" +_TTF_FONTFILE "arialbd.ttf" +_TTF_PSNAME "Arial-BoldMT" +ENDPROPERTIES +CHARS 96 +STARTCHAR 0020 +ENCODING 32 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR 0021 +ENCODING 33 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 2 10 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +00 +C0 +C0 +ENDCHAR +STARTCHAR 0022 +ENCODING 34 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 5 3 1 7 +BITMAP +D8 +D8 +D8 +ENDCHAR +STARTCHAR 0023 +ENCODING 35 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +24 +24 +24 +FC +48 +48 +FC +90 +90 +90 +ENDCHAR +STARTCHAR 0024 +ENCODING 36 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 12 1 -1 +BITMAP +20 +70 +A8 +A0 +E0 +F0 +78 +38 +28 +A8 +70 +20 +ENDCHAR +STARTCHAR 0025 +ENCODING 37 +SWIDTH 800 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +E4 +A4 +A4 +A8 +E8 +17 +15 +15 +25 +27 +ENDCHAR +STARTCHAR 0026 +ENCODING 38 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 8 10 1 0 +BITMAP +38 +6C +6C +3C +30 +7A +DA +CE +CE +7B +ENDCHAR +STARTCHAR 0027 +ENCODING 39 +SWIDTH 240 0 +DWIDTH 3 0 +BBX 2 3 1 7 +BITMAP +C0 +C0 +C0 +ENDCHAR +STARTCHAR 0028 +ENCODING 40 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 3 13 1 -3 +BITMAP +20 +60 +40 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +40 +60 +20 +ENDCHAR +STARTCHAR 0029 +ENCODING 41 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 3 13 0 -3 +BITMAP +80 +C0 +40 +60 +60 +60 +60 +60 +60 +60 +40 +C0 +80 +ENDCHAR +STARTCHAR 002A +ENCODING 42 +SWIDTH 400 0 +DWIDTH 5 0 +BBX 5 4 0 6 +BITMAP +20 +F8 +20 +D8 +ENDCHAR +STARTCHAR 002B +ENCODING 43 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 5 1 2 +BITMAP +30 +30 +FC +30 +30 +ENDCHAR +STARTCHAR 002C +ENCODING 44 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 2 4 1 -2 +BITMAP +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR 002D +ENCODING 45 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 3 1 1 2 +BITMAP +E0 +ENDCHAR +STARTCHAR 002E +ENCODING 46 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 2 2 1 0 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR 002F +ENCODING 47 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 4 10 0 0 +BITMAP +10 +10 +20 +20 +20 +40 +40 +40 +80 +80 +ENDCHAR +STARTCHAR 0030 +ENCODING 48 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +78 +CC +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR 0031 +ENCODING 49 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 4 10 1 0 +BITMAP +30 +70 +F0 +B0 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR 0032 +ENCODING 50 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +78 +CC +0C +0C +18 +38 +30 +60 +C0 +FC +ENDCHAR +STARTCHAR 0033 +ENCODING 51 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +78 +CC +0C +0C +30 +0C +0C +0C +CC +78 +ENDCHAR +STARTCHAR 0034 +ENCODING 52 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +18 +18 +38 +38 +58 +58 +98 +FC +18 +18 +ENDCHAR +STARTCHAR 0035 +ENCODING 53 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +7C +60 +C0 +F8 +CC +0C +0C +0C +CC +78 +ENDCHAR +STARTCHAR 0036 +ENCODING 54 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +38 +4C +C0 +C0 +F8 +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR 0037 +ENCODING 55 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +FC +0C +18 +18 +30 +30 +70 +60 +60 +60 +ENDCHAR +STARTCHAR 0038 +ENCODING 56 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +78 +CC +CC +CC +78 +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR 0039 +ENCODING 57 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +78 +CC +CC +CC +CC +7C +0C +0C +C8 +70 +ENDCHAR +STARTCHAR 003A +ENCODING 58 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 2 7 1 0 +BITMAP +C0 +C0 +00 +00 +00 +C0 +C0 +ENDCHAR +STARTCHAR 003B +ENCODING 59 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 2 9 1 -2 +BITMAP +C0 +C0 +00 +00 +00 +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR 003C +ENCODING 60 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 7 0 1 +BITMAP +04 +1C +F0 +C0 +70 +1C +04 +ENDCHAR +STARTCHAR 003D +ENCODING 61 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 7 3 0 3 +BITMAP +FE +00 +FE +ENDCHAR +STARTCHAR 003E +ENCODING 62 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 7 1 1 +BITMAP +80 +E0 +38 +0C +38 +E0 +80 +ENDCHAR +STARTCHAR 003F +ENCODING 63 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 7 10 0 0 +BITMAP +7C +C6 +06 +06 +0C +18 +30 +00 +30 +30 +ENDCHAR +STARTCHAR 0040 +ENCODING 64 +SWIDTH 1040 0 +DWIDTH 13 0 +BBX 13 13 0 -3 +BITMAP +0FC0 +3020 +6010 +4EC8 +9FC8 +B9C8 +B188 +B390 +BFB0 +5DC0 +4008 +3030 +0FC0 +ENDCHAR +STARTCHAR 0041 +ENCODING 65 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 9 10 0 0 +BITMAP +1C00 +1C00 +3600 +3600 +3600 +6300 +6300 +7F00 +C180 +C180 +ENDCHAR +STARTCHAR 0042 +ENCODING 66 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +FC +C6 +C6 +C6 +FC +C6 +C6 +C6 +C6 +FC +ENDCHAR +STARTCHAR 0043 +ENCODING 67 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 8 10 1 0 +BITMAP +3E +63 +C0 +C0 +C0 +C0 +C0 +C0 +63 +3E +ENDCHAR +STARTCHAR 0044 +ENCODING 68 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +F8 +CC +C6 +C6 +C6 +C6 +C6 +C6 +CC +F8 +ENDCHAR +STARTCHAR 0045 +ENCODING 69 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 10 1 0 +BITMAP +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR 0046 +ENCODING 70 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 10 1 0 +BITMAP +FC +C0 +C0 +C0 +C0 +FC +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR 0047 +ENCODING 71 +SWIDTH 800 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +3E +63 +C0 +C0 +C0 +CF +C3 +C3 +63 +3E +ENDCHAR +STARTCHAR 0048 +ENCODING 72 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +C6 +C6 +C6 +C6 +FE +C6 +C6 +C6 +C6 +C6 +ENDCHAR +STARTCHAR 0049 +ENCODING 73 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 2 10 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR 004A +ENCODING 74 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +0C +0C +0C +0C +0C +0C +0C +CC +CC +78 +ENDCHAR +STARTCHAR 004B +ENCODING 75 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +C6 +CC +D8 +D8 +F8 +EC +CC +CC +C6 +C6 +ENDCHAR +STARTCHAR 004C +ENCODING 76 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 10 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR 004D +ENCODING 77 +SWIDTH 880 0 +DWIDTH 11 0 +BBX 9 10 1 0 +BITMAP +E380 +E380 +F780 +F780 +D780 +D580 +D580 +DD80 +DD80 +C980 +ENDCHAR +STARTCHAR 004E +ENCODING 78 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +C6 +E6 +E6 +F6 +D6 +DE +CE +CE +C6 +C6 +ENDCHAR +STARTCHAR 004F +ENCODING 79 +SWIDTH 800 0 +DWIDTH 10 0 +BBX 8 10 1 0 +BITMAP +3C +66 +C3 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR 0050 +ENCODING 80 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +FC +C6 +C6 +C6 +C6 +FC +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR 0051 +ENCODING 81 +SWIDTH 800 0 +DWIDTH 10 0 +BBX 8 11 1 -1 +BITMAP +3C +66 +C3 +C3 +C3 +C3 +C3 +CB +66 +3E +01 +ENDCHAR +STARTCHAR 0052 +ENCODING 82 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 8 10 1 0 +BITMAP +FC +C6 +C6 +C6 +C6 +FC +CC +CE +C6 +C7 +ENDCHAR +STARTCHAR 0053 +ENCODING 83 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +7C +C6 +C0 +E0 +78 +3C +0E +06 +C6 +7C +ENDCHAR +STARTCHAR 0054 +ENCODING 84 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 8 10 0 0 +BITMAP +FF +18 +18 +18 +18 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR 0055 +ENCODING 85 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +C6 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +7C +ENDCHAR +STARTCHAR 0056 +ENCODING 86 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 9 10 0 0 +BITMAP +C180 +E180 +6300 +6300 +6300 +3600 +3600 +3600 +1C00 +1C00 +ENDCHAR +STARTCHAR 0057 +ENCODING 87 +SWIDTH 1040 0 +DWIDTH 13 0 +BBX 13 10 0 0 +BITMAP +C718 +C718 +6730 +6DB0 +6DB0 +6DB0 +6DB0 +38E0 +38E0 +38E0 +ENDCHAR +STARTCHAR 0058 +ENCODING 88 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +C6 +C6 +6C +38 +38 +38 +38 +6C +C6 +C6 +ENDCHAR +STARTCHAR 0059 +ENCODING 89 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 8 10 0 0 +BITMAP +C3 +C3 +66 +3C +3C +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR 005A +ENCODING 90 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +FE +06 +0C +18 +18 +30 +30 +60 +E0 +FE +ENDCHAR +STARTCHAR 005B +ENCODING 91 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 3 13 1 -3 +BITMAP +E0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +E0 +ENDCHAR +STARTCHAR 005C +ENCODING 92 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 4 10 0 0 +BITMAP +80 +80 +40 +40 +40 +20 +20 +20 +10 +10 +ENDCHAR +STARTCHAR 005D +ENCODING 93 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 3 13 0 -3 +BITMAP +E0 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +E0 +ENDCHAR +STARTCHAR 005E +ENCODING 94 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 5 0 4 +BITMAP +30 +30 +78 +48 +CC +ENDCHAR +STARTCHAR 005F +ENCODING 95 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 7 1 0 -3 +BITMAP +FE +ENDCHAR +STARTCHAR 0060 +ENCODING 96 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 3 2 0 8 +BITMAP +C0 +60 +ENDCHAR +STARTCHAR 0061 +ENCODING 97 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 7 1 0 +BITMAP +78 +8C +3C +6C +CC +CC +7C +ENDCHAR +STARTCHAR 0062 +ENCODING 98 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 10 1 0 +BITMAP +C0 +C0 +C0 +D8 +EC +CC +CC +CC +EC +D8 +ENDCHAR +STARTCHAR 0063 +ENCODING 99 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 7 1 0 +BITMAP +78 +CC +C0 +C0 +C0 +CC +78 +ENDCHAR +STARTCHAR 0064 +ENCODING 100 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 10 1 0 +BITMAP +0C +0C +0C +6C +DC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR 0065 +ENCODING 101 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 7 1 0 +BITMAP +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR 0066 +ENCODING 102 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 5 10 0 0 +BITMAP +38 +60 +60 +F0 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR 0067 +ENCODING 103 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 10 1 -3 +BITMAP +6C +DC +CC +CC +CC +DC +6C +0C +8C +78 +ENDCHAR +STARTCHAR 0068 +ENCODING 104 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 10 1 0 +BITMAP +C0 +C0 +C0 +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR 0069 +ENCODING 105 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 2 10 1 0 +BITMAP +C0 +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR 006A +ENCODING 106 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 4 13 -1 -3 +BITMAP +30 +30 +00 +30 +30 +30 +30 +30 +30 +30 +30 +30 +E0 +ENDCHAR +STARTCHAR 006B +ENCODING 107 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 1 0 +BITMAP +C0 +C0 +C0 +CC +D8 +F0 +F0 +D8 +D8 +CC +ENDCHAR +STARTCHAR 006C +ENCODING 108 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 2 10 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR 006D +ENCODING 109 +SWIDTH 960 0 +DWIDTH 12 0 +BBX 10 7 1 0 +BITMAP +DD80 +EEC0 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +ENDCHAR +STARTCHAR 006E +ENCODING 110 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 7 1 0 +BITMAP +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR 006F +ENCODING 111 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 7 1 0 +BITMAP +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR 0070 +ENCODING 112 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 10 1 -3 +BITMAP +D8 +EC +CC +CC +CC +EC +D8 +C0 +C0 +C0 +ENDCHAR +STARTCHAR 0071 +ENCODING 113 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 10 1 -3 +BITMAP +6C +DC +CC +CC +CC +DC +6C +0C +0C +0C +ENDCHAR +STARTCHAR 0072 +ENCODING 114 +SWIDTH 400 0 +DWIDTH 5 0 +BBX 4 7 1 0 +BITMAP +F0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR 0073 +ENCODING 115 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 7 0 0 +BITMAP +78 +CC +E0 +78 +1C +CC +78 +ENDCHAR +STARTCHAR 0074 +ENCODING 116 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 4 9 0 0 +BITMAP +20 +60 +F0 +60 +60 +60 +60 +60 +30 +ENDCHAR +STARTCHAR 0075 +ENCODING 117 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 7 1 0 +BITMAP +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR 0076 +ENCODING 118 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 7 7 0 0 +BITMAP +C6 +C6 +6C +6C +6C +38 +38 +ENDCHAR +STARTCHAR 0077 +ENCODING 119 +SWIDTH 880 0 +DWIDTH 11 0 +BBX 11 7 0 0 +BITMAP +C460 +CE60 +6EC0 +6AC0 +7BC0 +3B80 +3980 +ENDCHAR +STARTCHAR 0078 +ENCODING 120 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 7 1 0 +BITMAP +CC +CC +78 +30 +78 +CC +CC +ENDCHAR +STARTCHAR 0079 +ENCODING 121 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 7 10 0 -3 +BITMAP +C6 +C6 +6C +6C +6C +38 +38 +38 +30 +F0 +ENDCHAR +STARTCHAR 007A +ENCODING 122 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +F8 +18 +30 +60 +60 +C0 +F8 +ENDCHAR +STARTCHAR 007B +ENCODING 123 +SWIDTH 400 0 +DWIDTH 5 0 +BBX 5 13 0 -3 +BITMAP +38 +60 +60 +60 +60 +60 +C0 +60 +60 +60 +60 +60 +38 +ENDCHAR +STARTCHAR 007C +ENCODING 124 +SWIDTH 240 0 +DWIDTH 3 0 +BBX 1 12 1 -2 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR 007D +ENCODING 125 +SWIDTH 400 0 +DWIDTH 5 0 +BBX 5 13 0 -3 +BITMAP +E0 +30 +30 +30 +30 +30 +18 +30 +30 +30 +30 +30 +E0 +ENDCHAR +STARTCHAR 007E +ENCODING 126 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 7 2 0 3 +BITMAP +72 +9C +ENDCHAR +STARTCHAR 00A0 +ENCODING 160 +SWIDTH 320 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +ENDFONT diff --git a/gui/themes/fonts/README b/gui/themes/fonts/README new file mode 100644 index 0000000000..594bfc3ea4 --- /dev/null +++ b/gui/themes/fonts/README @@ -0,0 +1,3 @@ +These are fonts used in ScummVM. Most of them come from Xorg. + +Also other potentially usable fonts are stored here as well. diff --git a/gui/themes/fonts/clR6x12-iso-8859-1.bdf b/gui/themes/fonts/clR6x12-iso-8859-1.bdf new file mode 100644 index 0000000000..3e77859d72 --- /dev/null +++ b/gui/themes/fonts/clR6x12-iso-8859-1.bdf @@ -0,0 +1,4290 @@ +STARTFONT 2.1 +COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT! +COMMENT Generated with 'ucs2any.pl clR6x12.bdf ../../../fonts/util/map-ISO8859-1 ISO8859-1' +COMMENT from an ISO10646-1 encoded source BDF font. +COMMENT ucs2any.pl by Markus Kuhn <mkuhn@acm.org>, 2000. +COMMENT $Xorg: clR6x12.bdf,v 1.3 2000/08/18 15:17:40 xorgcvs Exp $ +COMMENT +COMMENT Copyright 1989 Dale Schumacher, dal@syntel.mn.org +COMMENT 399 Beacon Ave. +COMMENT St. Paul, MN 55104-3527 +COMMENT +COMMENT Permission to use, copy, modify, and distribute this software and +COMMENT its documentation for any purpose and without fee is hereby +COMMENT granted, provided that the above copyright notice appear in all +COMMENT copies and that both that copyright notice and this permission +COMMENT notice appear in supporting documentation, and that the name of +COMMENT Dale Schumacher not be used in advertising or publicity pertaining to +COMMENT distribution of the software without specific, written prior +COMMENT permission. Dale Schumacher makes no representations about the +COMMENT suitability of this software for any purpose. It is provided "as +COMMENT is" without express or implied warranty. +COMMENT +COMMENT +COMMENT Modified by Robert Brady, <rwb197@ecs.soton.ac.uk> +COMMENT +FONT -Schumacher-Clean-Medium-R-Normal--12-120-75-75-C-60-ISO8859-1 +SIZE 12 75 75 +FONTBOUNDINGBOX 6 12 0 -3 +STARTPROPERTIES 21 +FONTNAME_REGISTRY "" +FOUNDRY "Schumacher" +FAMILY_NAME "Clean" +WEIGHT_NAME "Medium" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 12 +POINT_SIZE 120 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "C" +AVERAGE_WIDTH 60 +CHARSET_REGISTRY "ISO8859" +CHARSET_ENCODING "1" +FONT_ASCENT 9 +FONT_DESCENT 3 +DEFAULT_CHAR 0 +COPYRIGHT "Copyright 1989 Dale Schumacher, 1999 Robert Brady." +CAP_HEIGHT 8 +X_HEIGHT 5 +ENDPROPERTIES +CHARS 223 +STARTCHAR defaultchar +ENCODING 0 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +A8 +00 +88 +00 +88 +00 +A8 +00 +00 +00 +ENDCHAR +STARTCHAR uni25C6 +ENCODING 1 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +20 +70 +F8 +70 +20 +00 +00 +00 +ENDCHAR +STARTCHAR shade +ENCODING 2 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +A8 +54 +A8 +54 +A8 +54 +A8 +54 +A8 +54 +A8 +54 +ENDCHAR +STARTCHAR uni2409 +ENCODING 3 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +A0 +A0 +E0 +A0 +BC +08 +08 +08 +08 +00 +00 +ENDCHAR +STARTCHAR uni240C +ENCODING 4 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +E0 +80 +C0 +9C +90 +1C +10 +10 +00 +00 +00 +ENDCHAR +STARTCHAR uni240D +ENCODING 5 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +60 +80 +80 +98 +74 +18 +14 +14 +00 +00 +00 +ENDCHAR +STARTCHAR uni240A +ENCODING 6 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +80 +80 +9C +F0 +18 +10 +10 +00 +00 +00 +ENDCHAR +STARTCHAR degree +ENCODING 7 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +48 +48 +30 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR plusminus +ENCODING 8 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +20 +F8 +20 +20 +00 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni2424 +ENCODING 9 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +A0 +E0 +E0 +E0 +B0 +10 +10 +10 +1C +00 +00 +00 +ENDCHAR +STARTCHAR uni240B +ENCODING 10 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +A0 +A0 +A0 +5C +48 +08 +08 +08 +00 +00 +00 +ENDCHAR +STARTCHAR SF040000 +ENCODING 11 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +E0 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF030000 +ENCODING 12 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +E0 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF010000 +ENCODING 13 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +3F +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF020000 +ENCODING 14 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +3F +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF050000 +ENCODING 15 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +FF +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni23BA +ENCODING 16 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +FC +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni23BB +ENCODING 17 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +FC +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF100000 +ENCODING 18 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +FC +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni23BC +ENCODING 19 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +FC +00 +00 +00 +ENDCHAR +STARTCHAR uni23BD +ENCODING 20 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +FC +ENDCHAR +STARTCHAR SF080000 +ENCODING 21 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +3F +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF090000 +ENCODING 22 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +E0 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF070000 +ENCODING 23 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +FF +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF060000 +ENCODING 24 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +FF +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF110000 +ENCODING 25 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +20 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR lessequal +ENCODING 26 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +18 +60 +80 +60 +18 +00 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR greaterequal +ENCODING 27 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +C0 +30 +08 +30 +C0 +00 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR pi +ENCODING 28 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F8 +88 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR notequal +ENCODING 29 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +10 +10 +F8 +20 +F8 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR sterling +ENCODING 30 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +48 +40 +E0 +40 +40 +48 +B0 +00 +00 +00 +ENDCHAR +STARTCHAR periodcentered +ENCODING 31 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +30 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR space +ENCODING 32 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +20 +20 +20 +20 +00 +20 +00 +00 +00 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +50 +50 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +50 +F8 +50 +F8 +50 +50 +00 +00 +00 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +78 +A0 +70 +28 +F0 +20 +00 +00 +00 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +C0 +C8 +10 +20 +40 +98 +18 +00 +00 +00 +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +80 +80 +40 +A8 +90 +68 +00 +00 +00 +ENDCHAR +STARTCHAR quotesingle +ENCODING 39 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +20 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +08 +10 +10 +20 +20 +20 +20 +20 +10 +10 +08 +00 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +20 +10 +10 +10 +10 +10 +20 +20 +40 +00 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +20 +A8 +70 +A8 +20 +00 +00 +00 +00 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +20 +20 +F8 +20 +20 +00 +00 +00 +00 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +30 +30 +20 +40 +00 +ENDCHAR +STARTCHAR hyphen +ENCODING 45 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +F8 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +30 +30 +00 +00 +00 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +08 +08 +10 +10 +20 +20 +40 +40 +80 +80 +00 +00 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +98 +A8 +C8 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +30 +10 +10 +10 +10 +10 +10 +00 +00 +00 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +08 +10 +20 +40 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +08 +30 +08 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +30 +30 +50 +50 +F8 +10 +38 +00 +00 +00 +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F8 +80 +80 +F0 +08 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +40 +80 +F0 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F8 +88 +08 +08 +10 +10 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +88 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +88 +88 +78 +08 +10 +60 +00 +00 +00 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +30 +30 +00 +00 +30 +30 +00 +00 +00 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +30 +30 +00 +00 +30 +30 +20 +40 +00 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +0C +30 +C0 +30 +0C +00 +00 +00 +00 +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F8 +00 +F8 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +C0 +30 +0C +30 +C0 +00 +00 +00 +00 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +08 +10 +20 +20 +00 +20 +00 +00 +00 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +B8 +B8 +B0 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +50 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +88 +88 +F0 +88 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +80 +80 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +E0 +90 +88 +88 +88 +90 +E0 +00 +00 +00 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +80 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +80 +80 +F0 +80 +80 +80 +00 +00 +00 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +98 +88 +88 +78 +00 +00 +00 +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +F8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +38 +08 +08 +08 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +90 +A0 +C0 +A0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +80 +80 +80 +80 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +D8 +A8 +A8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +C8 +C8 +A8 +98 +98 +88 +00 +00 +00 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +88 +88 +F0 +80 +80 +80 +00 +00 +00 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +88 +88 +88 +88 +70 +18 +00 +00 +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +88 +88 +F0 +A0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +70 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +50 +50 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +A8 +A8 +D8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +50 +20 +50 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +50 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +08 +10 +20 +40 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +38 +20 +20 +20 +20 +20 +20 +20 +20 +20 +38 +00 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +80 +80 +40 +40 +20 +20 +10 +10 +08 +08 +00 +00 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +70 +10 +10 +10 +10 +10 +10 +10 +10 +10 +70 +00 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +88 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +FC +00 +00 +ENDCHAR +STARTCHAR grave +ENCODING 96 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +10 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +80 +80 +F0 +88 +88 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +80 +80 +80 +78 +00 +00 +00 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +08 +08 +08 +78 +88 +88 +88 +78 +00 +00 +00 +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +38 +40 +40 +F0 +40 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +80 +80 +F0 +88 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +08 +08 +00 +38 +08 +08 +08 +08 +08 +08 +70 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +40 +40 +48 +50 +60 +50 +48 +00 +00 +00 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +60 +20 +20 +20 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +D0 +A8 +A8 +A8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +B0 +C8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F0 +88 +88 +88 +F0 +80 +80 +80 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +88 +88 +88 +78 +08 +08 +08 +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +58 +60 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +80 +70 +08 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +20 +70 +20 +20 +20 +18 +00 +00 +00 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +D8 +50 +50 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +A8 +A8 +A8 +50 +00 +00 +00 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +50 +20 +50 +88 +00 +00 +00 +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F8 +10 +20 +40 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +08 +10 +10 +10 +10 +20 +10 +10 +10 +10 +08 +00 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +20 +20 +20 +20 +20 +00 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +20 +20 +20 +10 +20 +20 +20 +20 +40 +00 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +40 +A8 +10 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR space +ENCODING 160 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR exclamdown +ENCODING 161 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +20 +20 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR cent +ENCODING 162 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +20 +70 +A8 +A0 +A8 +70 +20 +00 +00 +ENDCHAR +STARTCHAR sterling +ENCODING 163 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +48 +40 +E0 +40 +40 +48 +B0 +00 +00 +00 +ENDCHAR +STARTCHAR currency +ENCODING 164 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +70 +50 +70 +88 +00 +00 +00 +ENDCHAR +STARTCHAR yen +ENCODING 165 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +50 +20 +70 +20 +70 +20 +00 +00 +00 +ENDCHAR +STARTCHAR brokenbar +ENCODING 166 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +20 +20 +00 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR section +ENCODING 167 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +48 +40 +30 +48 +48 +48 +30 +08 +48 +30 +00 +ENDCHAR +STARTCHAR dieresis +ENCODING 168 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +50 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR copyright +ENCODING 169 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +78 +84 +B4 +A4 +A4 +B4 +84 +78 +00 +00 +00 +ENDCHAR +STARTCHAR ordfeminine +ENCODING 170 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +08 +38 +48 +38 +00 +78 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR guillemotleft +ENCODING 171 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +28 +50 +A0 +50 +28 +00 +00 +00 +00 +ENDCHAR +STARTCHAR logicalnot +ENCODING 172 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +78 +08 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR hyphen +ENCODING 173 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +78 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR registered +ENCODING 174 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +78 +84 +B4 +AC +B4 +AC +84 +78 +00 +00 +00 +ENDCHAR +STARTCHAR macron +ENCODING 175 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR degree +ENCODING 176 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +48 +48 +30 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR plusminus +ENCODING 177 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +20 +F8 +20 +20 +00 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR twosuperior +ENCODING 178 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +60 +10 +20 +40 +70 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR threesuperior +ENCODING 179 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +60 +10 +20 +10 +60 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR acute +ENCODING 180 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR mu +ENCODING 181 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +88 +C8 +B0 +80 +80 +00 +ENDCHAR +STARTCHAR paragraph +ENCODING 182 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +78 +E8 +E8 +68 +28 +28 +28 +00 +00 +00 +ENDCHAR +STARTCHAR periodcentered +ENCODING 183 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +30 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR cedilla +ENCODING 184 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +10 +20 +00 +ENDCHAR +STARTCHAR onesuperior +ENCODING 185 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +60 +20 +20 +20 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR ordmasculine +ENCODING 186 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +48 +48 +48 +30 +00 +78 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR guillemotright +ENCODING 187 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +A0 +50 +28 +50 +A0 +00 +00 +00 +00 +ENDCHAR +STARTCHAR onequarter +ENCODING 188 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +40 +40 +48 +10 +28 +38 +08 +00 +00 +00 +ENDCHAR +STARTCHAR onehalf +ENCODING 189 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +40 +40 +70 +08 +10 +20 +38 +00 +00 +00 +ENDCHAR +STARTCHAR threequarters +ENCODING 190 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +C0 +40 +20 +C8 +10 +28 +38 +08 +00 +00 +00 +ENDCHAR +STARTCHAR questiondown +ENCODING 191 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +20 +20 +40 +80 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +00 +70 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Aacute +ENCODING 193 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +70 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Acircumflex +ENCODING 194 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +00 +70 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Atilde +ENCODING 195 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +28 +50 +00 +70 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Adieresis +ENCODING 196 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +00 +70 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Aring +ENCODING 197 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +20 +70 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR AE +ENCODING 198 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +78 +A0 +A0 +B8 +E0 +A0 +B8 +00 +00 +00 +ENDCHAR +STARTCHAR Ccedilla +ENCODING 199 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +80 +80 +88 +70 +20 +40 +00 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +00 +F8 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Eacute +ENCODING 201 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +F8 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Ecircumflex +ENCODING 202 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +00 +F8 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Edieresis +ENCODING 203 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +00 +F8 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Igrave +ENCODING 204 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +00 +F8 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Iacute +ENCODING 205 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +F8 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Icircumflex +ENCODING 206 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +00 +F8 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Idieresis +ENCODING 207 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +00 +F8 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Eth +ENCODING 208 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +48 +44 +E4 +44 +48 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Ntilde +ENCODING 209 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +28 +50 +00 +88 +C8 +A8 +98 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +00 +70 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Oacute +ENCODING 211 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +70 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Ocircumflex +ENCODING 212 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +00 +70 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Otilde +ENCODING 213 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +28 +50 +00 +70 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Odieresis +ENCODING 214 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +00 +70 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR multiply +ENCODING 215 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +50 +20 +50 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Oslash +ENCODING 216 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +08 +78 +98 +A8 +A8 +A8 +C8 +F0 +80 +00 +00 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +00 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Uacute +ENCODING 218 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Ucircumflex +ENCODING 219 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +00 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Udieresis +ENCODING 220 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +00 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Yacute +ENCODING 221 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +88 +50 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR Thorn +ENCODING 222 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +F0 +88 +88 +88 +F0 +80 +80 +00 +00 +00 +ENDCHAR +STARTCHAR germandbls +ENCODING 223 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +48 +48 +D0 +50 +48 +48 +50 +00 +00 +00 +ENDCHAR +STARTCHAR agrave +ENCODING 224 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +20 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR aacute +ENCODING 225 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR acircumflex +ENCODING 226 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR atilde +ENCODING 227 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +28 +50 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR adieresis +ENCODING 228 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR aring +ENCODING 229 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +20 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR ae +ENCODING 230 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +28 +70 +A0 +78 +00 +00 +00 +ENDCHAR +STARTCHAR ccedilla +ENCODING 231 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +80 +80 +80 +78 +20 +40 +00 +ENDCHAR +STARTCHAR egrave +ENCODING 232 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +20 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR eacute +ENCODING 233 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR ecircumflex +ENCODING 234 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR edieresis +ENCODING 235 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR igrave +ENCODING 236 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +20 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR iacute +ENCODING 237 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +40 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR icircumflex +ENCODING 238 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR idieresis +ENCODING 239 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR eth +ENCODING 240 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +28 +10 +28 +08 +78 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR ntilde +ENCODING 241 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +28 +50 +00 +B0 +C8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR ograve +ENCODING 242 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +20 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR oacute +ENCODING 243 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR ocircumflex +ENCODING 244 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR otilde +ENCODING 245 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +28 +50 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR odieresis +ENCODING 246 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR divide +ENCODING 247 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +20 +00 +F8 +00 +20 +00 +00 +00 +ENDCHAR +STARTCHAR oslash +ENCODING 248 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +08 +78 +98 +A8 +C8 +F0 +80 +00 +00 +ENDCHAR +STARTCHAR ugrave +ENCODING 249 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +20 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR uacute +ENCODING 250 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR ucircumflex +ENCODING 251 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR udieresis +ENCODING 252 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR yacute +ENCODING 253 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +88 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR thorn +ENCODING 254 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +80 +80 +B0 +C8 +88 +C8 +B0 +80 +80 +00 +ENDCHAR +STARTCHAR ydieresis +ENCODING 255 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +00 +88 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +ENDFONT diff --git a/gui/themes/fonts/clR6x12-iso-8859-5.bdf b/gui/themes/fonts/clR6x12-iso-8859-5.bdf new file mode 100644 index 0000000000..4a4a674235 --- /dev/null +++ b/gui/themes/fonts/clR6x12-iso-8859-5.bdf @@ -0,0 +1,4291 @@ +STARTFONT 2.1 +COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT! +COMMENT Generated with 'ucs2any clR6x12.bdf /usr/share/fonts/X11/util/map-ISO8859-5 ISO8859-5' +COMMENT from an ISO10646-1 encoded source BDF font. +COMMENT ucs2any by Ben Collver <collver1@attbi.com>, 2003, based on +COMMENT ucs2any.pl by Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>, 2000. +COMMENT $XConsortium: clR6x12.bdf,v 1.2 94/04/11 12:08:30 gildea Exp $ +COMMENT +COMMENT Copyright 1989 Dale Schumacher, dal@syntel.mn.org +COMMENT 399 Beacon Ave. +COMMENT St. Paul, MN 55104-3527 +COMMENT +COMMENT Permission to use, copy, modify, and distribute this software and +COMMENT its documentation for any purpose and without fee is hereby +COMMENT granted, provided that the above copyright notice appear in all +COMMENT copies and that both that copyright notice and this permission +COMMENT notice appear in supporting documentation, and that the name of +COMMENT Dale Schumacher not be used in advertising or publicity pertaining to +COMMENT distribution of the software without specific, written prior +COMMENT permission. Dale Schumacher makes no representations about the +COMMENT suitability of this software for any purpose. It is provided "as +COMMENT is" without express or implied warranty. +COMMENT +COMMENT +COMMENT Modified by Robert Brady, <rwb197@ecs.soton.ac.uk> +COMMENT +FONT -Schumacher-Clean-Medium-R-Normal--12-120-75-75-C-60-ISO8859-5 +SIZE 12 75 75 +FONTBOUNDINGBOX 6 12 0 -3 +STARTPROPERTIES 21 +FONTNAME_REGISTRY "" +FOUNDRY "Schumacher" +FAMILY_NAME "Clean" +WEIGHT_NAME "Medium" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 12 +POINT_SIZE 120 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "C" +AVERAGE_WIDTH 60 +CHARSET_REGISTRY "ISO8859" +CHARSET_ENCODING "5" +FONT_ASCENT 9 +FONT_DESCENT 3 +DEFAULT_CHAR 0 +COPYRIGHT "Copyright 1989 Dale Schumacher, 1999 Robert Brady." +CAP_HEIGHT 8 +X_HEIGHT 5 +ENDPROPERTIES +CHARS 223 +STARTCHAR defaultchar +ENCODING 0 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +A8 +00 +88 +00 +88 +00 +A8 +00 +00 +00 +ENDCHAR +STARTCHAR uni25C6 +ENCODING 1 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +20 +70 +F8 +70 +20 +00 +00 +00 +ENDCHAR +STARTCHAR shade +ENCODING 2 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +A8 +54 +A8 +54 +A8 +54 +A8 +54 +A8 +54 +A8 +54 +ENDCHAR +STARTCHAR uni2409 +ENCODING 3 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +A0 +A0 +E0 +A0 +BC +08 +08 +08 +08 +00 +00 +ENDCHAR +STARTCHAR uni240C +ENCODING 4 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +E0 +80 +C0 +9C +90 +1C +10 +10 +00 +00 +00 +ENDCHAR +STARTCHAR uni240D +ENCODING 5 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +60 +80 +80 +98 +74 +18 +14 +14 +00 +00 +00 +ENDCHAR +STARTCHAR uni240A +ENCODING 6 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +80 +80 +9C +F0 +18 +10 +10 +00 +00 +00 +ENDCHAR +STARTCHAR degree +ENCODING 7 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +48 +48 +30 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR plusminus +ENCODING 8 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +20 +F8 +20 +20 +00 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni2424 +ENCODING 9 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +A0 +E0 +E0 +E0 +B0 +10 +10 +10 +1C +00 +00 +00 +ENDCHAR +STARTCHAR uni240B +ENCODING 10 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +A0 +A0 +A0 +5C +48 +08 +08 +08 +00 +00 +00 +ENDCHAR +STARTCHAR SF040000 +ENCODING 11 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +E0 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF030000 +ENCODING 12 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +E0 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF010000 +ENCODING 13 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +3F +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF020000 +ENCODING 14 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +3F +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF050000 +ENCODING 15 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +FF +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni23BA +ENCODING 16 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +FC +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni23BB +ENCODING 17 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +FC +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF100000 +ENCODING 18 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +FC +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni23BC +ENCODING 19 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +FC +00 +00 +00 +ENDCHAR +STARTCHAR uni23BD +ENCODING 20 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +FC +ENDCHAR +STARTCHAR SF080000 +ENCODING 21 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +3F +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF090000 +ENCODING 22 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +E0 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF070000 +ENCODING 23 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +FF +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF060000 +ENCODING 24 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +FF +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF110000 +ENCODING 25 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +20 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR lessequal +ENCODING 26 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +18 +60 +80 +60 +18 +00 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR greaterequal +ENCODING 27 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +C0 +30 +08 +30 +C0 +00 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR pi +ENCODING 28 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F8 +88 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR notequal +ENCODING 29 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +10 +10 +F8 +20 +F8 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR sterling +ENCODING 30 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +48 +40 +E0 +40 +40 +48 +B0 +00 +00 +00 +ENDCHAR +STARTCHAR periodcentered +ENCODING 31 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +30 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR space +ENCODING 32 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +20 +20 +20 +20 +00 +20 +00 +00 +00 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +50 +50 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +50 +F8 +50 +F8 +50 +50 +00 +00 +00 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +78 +A0 +70 +28 +F0 +20 +00 +00 +00 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +C0 +C8 +10 +20 +40 +98 +18 +00 +00 +00 +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +80 +80 +40 +A8 +90 +68 +00 +00 +00 +ENDCHAR +STARTCHAR quotesingle +ENCODING 39 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +20 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +08 +10 +10 +20 +20 +20 +20 +20 +10 +10 +08 +00 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +20 +10 +10 +10 +10 +10 +20 +20 +40 +00 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +20 +A8 +70 +A8 +20 +00 +00 +00 +00 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +20 +20 +F8 +20 +20 +00 +00 +00 +00 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +30 +30 +20 +40 +00 +ENDCHAR +STARTCHAR hyphen +ENCODING 45 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +F8 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +30 +30 +00 +00 +00 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +08 +08 +10 +10 +20 +20 +40 +40 +80 +80 +00 +00 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +98 +A8 +C8 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +30 +10 +10 +10 +10 +10 +10 +00 +00 +00 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +08 +10 +20 +40 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +08 +30 +08 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +30 +30 +50 +50 +F8 +10 +38 +00 +00 +00 +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F8 +80 +80 +F0 +08 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +40 +80 +F0 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F8 +88 +08 +08 +10 +10 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +88 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +88 +88 +78 +08 +10 +60 +00 +00 +00 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +30 +30 +00 +00 +30 +30 +00 +00 +00 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +30 +30 +00 +00 +30 +30 +20 +40 +00 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +0C +30 +C0 +30 +0C +00 +00 +00 +00 +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F8 +00 +F8 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +C0 +30 +0C +30 +C0 +00 +00 +00 +00 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +08 +10 +20 +20 +00 +20 +00 +00 +00 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +B8 +B8 +B0 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +50 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +88 +88 +F0 +88 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +80 +80 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +E0 +90 +88 +88 +88 +90 +E0 +00 +00 +00 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +80 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +80 +80 +F0 +80 +80 +80 +00 +00 +00 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +98 +88 +88 +78 +00 +00 +00 +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +F8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +38 +08 +08 +08 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +90 +A0 +C0 +A0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +80 +80 +80 +80 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +D8 +A8 +A8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +C8 +C8 +A8 +98 +98 +88 +00 +00 +00 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +88 +88 +F0 +80 +80 +80 +00 +00 +00 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +88 +88 +88 +88 +70 +18 +00 +00 +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +88 +88 +F0 +A0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +70 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +50 +50 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +A8 +A8 +D8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +50 +20 +50 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +50 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +08 +10 +20 +40 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +38 +20 +20 +20 +20 +20 +20 +20 +20 +20 +38 +00 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +80 +80 +40 +40 +20 +20 +10 +10 +08 +08 +00 +00 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +70 +10 +10 +10 +10 +10 +10 +10 +10 +10 +70 +00 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +88 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +FC +00 +00 +ENDCHAR +STARTCHAR grave +ENCODING 96 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +10 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +80 +80 +F0 +88 +88 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +80 +80 +80 +78 +00 +00 +00 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +08 +08 +08 +78 +88 +88 +88 +78 +00 +00 +00 +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +38 +40 +40 +F0 +40 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +80 +80 +F0 +88 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +08 +08 +00 +38 +08 +08 +08 +08 +08 +08 +70 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +40 +40 +48 +50 +60 +50 +48 +00 +00 +00 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +60 +20 +20 +20 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +D0 +A8 +A8 +A8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +B0 +C8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F0 +88 +88 +88 +F0 +80 +80 +80 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +88 +88 +88 +78 +08 +08 +08 +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +58 +60 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +80 +70 +08 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +20 +70 +20 +20 +20 +18 +00 +00 +00 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +D8 +50 +50 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +A8 +A8 +A8 +50 +00 +00 +00 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +50 +20 +50 +88 +00 +00 +00 +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F8 +10 +20 +40 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +08 +10 +10 +10 +10 +20 +10 +10 +10 +10 +08 +00 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +20 +20 +20 +20 +20 +00 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +20 +20 +20 +10 +20 +20 +20 +20 +40 +00 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +40 +A8 +10 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR space +ENCODING 160 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR afii10023 +ENCODING 161 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +00 +F8 +80 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10051 +ENCODING 162 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +E0 +40 +40 +70 +48 +48 +48 +08 +30 +00 +ENDCHAR +STARTCHAR afii10052 +ENCODING 163 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +78 +40 +40 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR afii10053 +ENCODING 164 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +F0 +80 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10054 +ENCODING 165 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +70 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10055 +ENCODING 166 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10056 +ENCODING 167 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +00 +F8 +20 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10057 +ENCODING 168 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +38 +08 +08 +08 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10058 +ENCODING 169 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +60 +A0 +A0 +B0 +A8 +A8 +A8 +B0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10059 +ENCODING 170 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +A0 +A0 +A0 +F0 +A8 +A8 +A8 +B0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10060 +ENCODING 171 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +E0 +40 +40 +70 +48 +48 +48 +00 +00 +00 +ENDCHAR +STARTCHAR afii10061 +ENCODING 172 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +88 +90 +E0 +90 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR hyphen +ENCODING 173 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +78 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR afii10062 +ENCODING 174 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +88 +70 +00 +88 +88 +88 +78 +08 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10145 +ENCODING 175 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +88 +88 +88 +F8 +20 +20 +00 +ENDCHAR +STARTCHAR afii10017 +ENCODING 176 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +50 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10018 +ENCODING 177 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +80 +80 +F0 +88 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10019 +ENCODING 178 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +88 +88 +F0 +88 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10020 +ENCODING 179 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +78 +40 +40 +40 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR afii10021 +ENCODING 180 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +30 +50 +50 +50 +50 +50 +F8 +88 +00 +00 +ENDCHAR +STARTCHAR afii10022 +ENCODING 181 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +80 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10024 +ENCODING 182 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +A8 +A8 +A8 +70 +A8 +A8 +A8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10025 +ENCODING 183 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +08 +10 +08 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10026 +ENCODING 184 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +98 +98 +A8 +C8 +C8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10027 +ENCODING 185 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +88 +70 +88 +98 +98 +A8 +C8 +C8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10028 +ENCODING 186 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +90 +A0 +C0 +A0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10029 +ENCODING 187 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +38 +48 +48 +48 +48 +48 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10030 +ENCODING 188 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +D8 +A8 +A8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10031 +ENCODING 189 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +F8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10032 +ENCODING 190 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10033 +ENCODING 191 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +88 +88 +88 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10034 +ENCODING 192 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +88 +88 +F0 +80 +80 +80 +00 +00 +00 +ENDCHAR +STARTCHAR afii10035 +ENCODING 193 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +80 +80 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10036 +ENCODING 194 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR afii10037 +ENCODING 195 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +78 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10038 +ENCODING 196 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +20 +70 +A8 +A8 +70 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10039 +ENCODING 197 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +50 +20 +50 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10040 +ENCODING 198 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +90 +90 +90 +90 +90 +90 +F8 +08 +00 +00 +ENDCHAR +STARTCHAR afii10041 +ENCODING 199 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +78 +08 +08 +08 +00 +00 +00 +ENDCHAR +STARTCHAR afii10042 +ENCODING 200 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +A8 +A8 +A8 +A8 +A8 +A8 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10043 +ENCODING 201 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +A8 +A8 +A8 +A8 +A8 +A8 +F8 +08 +08 +00 +ENDCHAR +STARTCHAR afii10044 +ENCODING 202 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +C0 +40 +40 +70 +48 +48 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10045 +ENCODING 203 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +E8 +98 +98 +E8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10046 +ENCODING 204 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +80 +80 +80 +F0 +88 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10047 +ENCODING 205 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +08 +78 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10048 +ENCODING 206 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +90 +A8 +A8 +E8 +A8 +A8 +90 +00 +00 +00 +ENDCHAR +STARTCHAR afii10049 +ENCODING 207 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +78 +88 +88 +78 +28 +48 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10065 +ENCODING 208 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +08 +78 +88 +78 +00 +00 +00 +ENDCHAR +STARTCHAR afii10066 +ENCODING 209 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +80 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10067 +ENCODING 210 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F0 +88 +F0 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10068 +ENCODING 211 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +40 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR afii10069 +ENCODING 212 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +30 +50 +50 +50 +F8 +88 +00 +00 +ENDCHAR +STARTCHAR afii10070 +ENCODING 213 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10072 +ENCODING 214 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +A8 +A8 +70 +A8 +A8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10073 +ENCODING 215 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +30 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10074 +ENCODING 216 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +98 +A8 +C8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10075 +ENCODING 217 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +88 +70 +00 +88 +98 +A8 +C8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10076 +ENCODING 218 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +90 +E0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10077 +ENCODING 219 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +38 +48 +48 +48 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10078 +ENCODING 220 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +D8 +A8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10079 +ENCODING 221 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10080 +ENCODING 222 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10081 +ENCODING 223 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F8 +88 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10082 +ENCODING 224 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F0 +88 +88 +88 +F0 +80 +80 +80 +ENDCHAR +STARTCHAR afii10083 +ENCODING 225 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +80 +80 +80 +78 +00 +00 +00 +ENDCHAR +STARTCHAR afii10084 +ENCODING 226 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F8 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR afii10085 +ENCODING 227 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR afii10086 +ENCODING 228 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +20 +70 +A8 +A8 +A8 +70 +20 +20 +00 +ENDCHAR +STARTCHAR afii10087 +ENCODING 229 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +50 +20 +50 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10088 +ENCODING 230 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +90 +90 +90 +90 +F8 +08 +00 +00 +ENDCHAR +STARTCHAR afii10089 +ENCODING 231 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +78 +08 +08 +00 +00 +00 +ENDCHAR +STARTCHAR afii10090 +ENCODING 232 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +A8 +A8 +A8 +A8 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10091 +ENCODING 233 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +A8 +A8 +A8 +A8 +F8 +08 +08 +00 +ENDCHAR +STARTCHAR afii10092 +ENCODING 234 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +C0 +40 +70 +48 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10093 +ENCODING 235 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +E8 +98 +E8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10094 +ENCODING 236 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +80 +80 +F0 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10095 +ENCODING 237 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +38 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10096 +ENCODING 238 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +90 +A8 +E8 +A8 +90 +00 +00 +00 +ENDCHAR +STARTCHAR afii10097 +ENCODING 239 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +88 +78 +48 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii61352 +ENCODING 240 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +A0 +A0 +E0 +E8 +F4 +B4 +A8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10071 +ENCODING 241 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10099 +ENCODING 242 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +F0 +40 +78 +44 +44 +44 +44 +04 +18 +00 +ENDCHAR +STARTCHAR afii10100 +ENCODING 243 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +78 +40 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR afii10101 +ENCODING 244 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +E0 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10102 +ENCODING 245 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +80 +70 +08 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10103 +ENCODING 246 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10104 +ENCODING 247 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10105 +ENCODING 248 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +08 +00 +38 +08 +08 +08 +08 +08 +08 +70 +ENDCHAR +STARTCHAR afii10106 +ENCODING 249 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +60 +A0 +B0 +A8 +B0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10107 +ENCODING 250 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +A0 +A0 +F0 +A8 +B0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10108 +ENCODING 251 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +F0 +40 +78 +44 +44 +44 +44 +00 +00 +00 +ENDCHAR +STARTCHAR afii10109 +ENCODING 252 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +88 +90 +E0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR section +ENCODING 253 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +48 +40 +30 +48 +48 +48 +30 +08 +48 +30 +00 +ENDCHAR +STARTCHAR afii10110 +ENCODING 254 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +88 +70 +00 +88 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR afii10193 +ENCODING 255 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +88 +88 +F8 +20 +20 +00 +ENDCHAR +ENDFONT diff --git a/gui/themes/fonts/clR6x12.bdf b/gui/themes/fonts/clR6x12.bdf new file mode 100644 index 0000000000..0e0924f857 --- /dev/null +++ b/gui/themes/fonts/clR6x12.bdf @@ -0,0 +1,22736 @@ +STARTFONT 2.1 +COMMENT $XConsortium: clR6x12.bdf,v 1.2 94/04/11 12:08:30 gildea Exp $ +COMMENT +COMMENT Copyright 1989 Dale Schumacher, dal@syntel.mn.org +COMMENT 399 Beacon Ave. +COMMENT St. Paul, MN 55104-3527 +COMMENT +COMMENT Permission to use, copy, modify, and distribute this software and +COMMENT its documentation for any purpose and without fee is hereby +COMMENT granted, provided that the above copyright notice appear in all +COMMENT copies and that both that copyright notice and this permission +COMMENT notice appear in supporting documentation, and that the name of +COMMENT Dale Schumacher not be used in advertising or publicity pertaining to +COMMENT distribution of the software without specific, written prior +COMMENT permission. Dale Schumacher makes no representations about the +COMMENT suitability of this software for any purpose. It is provided "as +COMMENT is" without express or implied warranty. +COMMENT +COMMENT +COMMENT Modified by Robert Brady, <rwb197@ecs.soton.ac.uk> +COMMENT +FONT -Schumacher-Clean-Medium-R-Normal--12-120-75-75-C-60-ISO10646-1 +SIZE 12 75 75 +FONTBOUNDINGBOX 6 12 0 -3 +STARTPROPERTIES 22 +FONTNAME_REGISTRY "" +FOUNDRY "Schumacher" +FAMILY_NAME "Clean" +WEIGHT_NAME "Medium" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 12 +POINT_SIZE 120 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "C" +AVERAGE_WIDTH 60 +CHARSET_REGISTRY "ISO10646" +CHARSET_ENCODING "1" +FONT_ASCENT 9 +FONT_DESCENT 3 +DEFAULT_CHAR 0 +COPYRIGHT "Copyright 1989 Dale Schumacher, 1999 Robert Brady." +_XMBDFED_INFO "Edited with xmbdfed 4.5." +CAP_HEIGHT 8 +X_HEIGHT 5 +ENDPROPERTIES +CHARS 1194 +STARTCHAR char0 +ENCODING 0 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +A8 +00 +88 +00 +88 +00 +A8 +00 +00 +00 +ENDCHAR +STARTCHAR space +ENCODING 32 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +20 +20 +20 +20 +00 +20 +00 +00 +00 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +50 +50 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +50 +F8 +50 +F8 +50 +50 +00 +00 +00 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +78 +A0 +70 +28 +F0 +20 +00 +00 +00 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +C0 +C8 +10 +20 +40 +98 +18 +00 +00 +00 +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +80 +80 +40 +A8 +90 +68 +00 +00 +00 +ENDCHAR +STARTCHAR quotesingle +ENCODING 39 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +20 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +08 +10 +10 +20 +20 +20 +20 +20 +10 +10 +08 +00 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +20 +10 +10 +10 +10 +10 +20 +20 +40 +00 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +20 +A8 +70 +A8 +20 +00 +00 +00 +00 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +20 +20 +F8 +20 +20 +00 +00 +00 +00 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +30 +30 +20 +40 +00 +ENDCHAR +STARTCHAR hyphen +ENCODING 45 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +F8 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +30 +30 +00 +00 +00 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +08 +08 +10 +10 +20 +20 +40 +40 +80 +80 +00 +00 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +98 +A8 +C8 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +30 +10 +10 +10 +10 +10 +10 +00 +00 +00 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +08 +10 +20 +40 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +08 +30 +08 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +30 +30 +50 +50 +F8 +10 +38 +00 +00 +00 +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F8 +80 +80 +F0 +08 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +40 +80 +F0 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F8 +88 +08 +08 +10 +10 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +88 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +88 +88 +78 +08 +10 +60 +00 +00 +00 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +30 +30 +00 +00 +30 +30 +00 +00 +00 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +30 +30 +00 +00 +30 +30 +20 +40 +00 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +0C +30 +C0 +30 +0C +00 +00 +00 +00 +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F8 +00 +F8 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +C0 +30 +0C +30 +C0 +00 +00 +00 +00 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +08 +10 +20 +20 +00 +20 +00 +00 +00 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +B8 +B8 +B0 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +50 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +88 +88 +F0 +88 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +80 +80 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +E0 +90 +88 +88 +88 +90 +E0 +00 +00 +00 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +80 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +80 +80 +F0 +80 +80 +80 +00 +00 +00 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +98 +88 +88 +78 +00 +00 +00 +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +F8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +38 +08 +08 +08 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +90 +A0 +C0 +A0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +80 +80 +80 +80 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +D8 +A8 +A8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +C8 +C8 +A8 +98 +98 +88 +00 +00 +00 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +88 +88 +F0 +80 +80 +80 +00 +00 +00 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +88 +88 +88 +88 +70 +18 +00 +00 +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +88 +88 +F0 +A0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +70 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +50 +50 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +A8 +A8 +D8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +50 +20 +50 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +50 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +08 +10 +20 +40 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +38 +20 +20 +20 +20 +20 +20 +20 +20 +20 +38 +00 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +80 +80 +40 +40 +20 +20 +10 +10 +08 +08 +00 +00 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +70 +10 +10 +10 +10 +10 +10 +10 +10 +10 +70 +00 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +88 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +FC +00 +00 +ENDCHAR +STARTCHAR grave +ENCODING 96 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +10 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +80 +80 +F0 +88 +88 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +80 +80 +80 +78 +00 +00 +00 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +08 +08 +08 +78 +88 +88 +88 +78 +00 +00 +00 +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +38 +40 +40 +F0 +40 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +80 +80 +F0 +88 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +08 +08 +00 +38 +08 +08 +08 +08 +08 +08 +70 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +40 +40 +48 +50 +60 +50 +48 +00 +00 +00 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +60 +20 +20 +20 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +D0 +A8 +A8 +A8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +B0 +C8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F0 +88 +88 +88 +F0 +80 +80 +80 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +88 +88 +88 +78 +08 +08 +08 +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +58 +60 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +80 +70 +08 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +20 +70 +20 +20 +20 +18 +00 +00 +00 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +D8 +50 +50 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +A8 +A8 +A8 +50 +00 +00 +00 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +50 +20 +50 +88 +00 +00 +00 +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F8 +10 +20 +40 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +08 +10 +10 +10 +10 +20 +10 +10 +10 +10 +08 +00 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +20 +20 +20 +20 +20 +00 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +20 +20 +20 +10 +20 +20 +20 +20 +40 +00 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +40 +A8 +10 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR space +ENCODING 160 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR exclamdown +ENCODING 161 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +20 +20 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR cent +ENCODING 162 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +20 +70 +A8 +A0 +A8 +70 +20 +00 +00 +ENDCHAR +STARTCHAR sterling +ENCODING 163 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +48 +40 +E0 +40 +40 +48 +B0 +00 +00 +00 +ENDCHAR +STARTCHAR currency +ENCODING 164 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +70 +50 +70 +88 +00 +00 +00 +ENDCHAR +STARTCHAR yen +ENCODING 165 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +50 +20 +70 +20 +70 +20 +00 +00 +00 +ENDCHAR +STARTCHAR brokenbar +ENCODING 166 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +20 +20 +00 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR section +ENCODING 167 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +48 +40 +30 +48 +48 +48 +30 +08 +48 +30 +00 +ENDCHAR +STARTCHAR dieresis +ENCODING 168 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +50 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR copyright +ENCODING 169 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +78 +84 +B4 +A4 +A4 +B4 +84 +78 +00 +00 +00 +ENDCHAR +STARTCHAR ordfeminine +ENCODING 170 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +08 +38 +48 +38 +00 +78 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR guillemotleft +ENCODING 171 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +28 +50 +A0 +50 +28 +00 +00 +00 +00 +ENDCHAR +STARTCHAR logicalnot +ENCODING 172 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +78 +08 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR hyphen +ENCODING 173 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +78 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR registered +ENCODING 174 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +78 +84 +B4 +AC +B4 +AC +84 +78 +00 +00 +00 +ENDCHAR +STARTCHAR macron +ENCODING 175 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR degree +ENCODING 176 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +48 +48 +30 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR plusminus +ENCODING 177 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +20 +F8 +20 +20 +00 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR twosuperior +ENCODING 178 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +60 +10 +20 +40 +70 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR threesuperior +ENCODING 179 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +60 +10 +20 +10 +60 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR acute +ENCODING 180 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR mu +ENCODING 181 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +88 +C8 +B0 +80 +80 +00 +ENDCHAR +STARTCHAR paragraph +ENCODING 182 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +78 +E8 +E8 +68 +28 +28 +28 +00 +00 +00 +ENDCHAR +STARTCHAR periodcentered +ENCODING 183 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +30 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR cedilla +ENCODING 184 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +10 +20 +00 +ENDCHAR +STARTCHAR onesuperior +ENCODING 185 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +60 +20 +20 +20 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR ordmasculine +ENCODING 186 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +48 +48 +48 +30 +00 +78 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR guillemotright +ENCODING 187 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +A0 +50 +28 +50 +A0 +00 +00 +00 +00 +ENDCHAR +STARTCHAR onequarter +ENCODING 188 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +40 +40 +48 +10 +28 +38 +08 +00 +00 +00 +ENDCHAR +STARTCHAR onehalf +ENCODING 189 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +40 +40 +70 +08 +10 +20 +38 +00 +00 +00 +ENDCHAR +STARTCHAR threequarters +ENCODING 190 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +C0 +40 +20 +C8 +10 +28 +38 +08 +00 +00 +00 +ENDCHAR +STARTCHAR questiondown +ENCODING 191 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +20 +20 +40 +80 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +00 +70 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Aacute +ENCODING 193 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +70 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Acircumflex +ENCODING 194 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +00 +70 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Atilde +ENCODING 195 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +28 +50 +00 +70 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Adieresis +ENCODING 196 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +00 +70 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Aring +ENCODING 197 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +20 +70 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR AE +ENCODING 198 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +78 +A0 +A0 +B8 +E0 +A0 +B8 +00 +00 +00 +ENDCHAR +STARTCHAR Ccedilla +ENCODING 199 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +80 +80 +88 +70 +20 +40 +00 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +00 +F8 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Eacute +ENCODING 201 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +F8 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Ecircumflex +ENCODING 202 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +00 +F8 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Edieresis +ENCODING 203 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +00 +F8 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Igrave +ENCODING 204 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +00 +F8 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Iacute +ENCODING 205 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +F8 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Icircumflex +ENCODING 206 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +00 +F8 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Idieresis +ENCODING 207 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +00 +F8 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Eth +ENCODING 208 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +48 +44 +E4 +44 +48 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Ntilde +ENCODING 209 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +28 +50 +00 +88 +C8 +A8 +98 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +00 +70 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Oacute +ENCODING 211 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +70 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Ocircumflex +ENCODING 212 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +00 +70 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Otilde +ENCODING 213 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +28 +50 +00 +70 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Odieresis +ENCODING 214 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +00 +70 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR multiply +ENCODING 215 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +50 +20 +50 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Oslash +ENCODING 216 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +08 +78 +98 +A8 +A8 +A8 +C8 +F0 +80 +00 +00 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +00 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Uacute +ENCODING 218 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Ucircumflex +ENCODING 219 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +00 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Udieresis +ENCODING 220 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +00 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Yacute +ENCODING 221 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +88 +50 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR Thorn +ENCODING 222 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +F0 +88 +88 +88 +F0 +80 +80 +00 +00 +00 +ENDCHAR +STARTCHAR germandbls +ENCODING 223 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +48 +48 +D0 +50 +48 +48 +50 +00 +00 +00 +ENDCHAR +STARTCHAR agrave +ENCODING 224 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +20 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR aacute +ENCODING 225 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR acircumflex +ENCODING 226 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR atilde +ENCODING 227 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +28 +50 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR adieresis +ENCODING 228 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR aring +ENCODING 229 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +20 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR ae +ENCODING 230 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +28 +70 +A0 +78 +00 +00 +00 +ENDCHAR +STARTCHAR ccedilla +ENCODING 231 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +80 +80 +80 +78 +20 +40 +00 +ENDCHAR +STARTCHAR egrave +ENCODING 232 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +20 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR eacute +ENCODING 233 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR ecircumflex +ENCODING 234 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR edieresis +ENCODING 235 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR igrave +ENCODING 236 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +20 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR iacute +ENCODING 237 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +40 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR icircumflex +ENCODING 238 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR idieresis +ENCODING 239 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR eth +ENCODING 240 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +28 +10 +28 +08 +78 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR ntilde +ENCODING 241 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +28 +50 +00 +B0 +C8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR ograve +ENCODING 242 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +20 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR oacute +ENCODING 243 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR ocircumflex +ENCODING 244 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR otilde +ENCODING 245 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +28 +50 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR odieresis +ENCODING 246 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR divide +ENCODING 247 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +20 +00 +F8 +00 +20 +00 +00 +00 +ENDCHAR +STARTCHAR oslash +ENCODING 248 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +08 +78 +98 +A8 +C8 +F0 +80 +00 +00 +ENDCHAR +STARTCHAR ugrave +ENCODING 249 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +20 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR uacute +ENCODING 250 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR ucircumflex +ENCODING 251 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR udieresis +ENCODING 252 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR yacute +ENCODING 253 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +88 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR thorn +ENCODING 254 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +80 +80 +B0 +C8 +88 +C8 +B0 +80 +80 +00 +ENDCHAR +STARTCHAR ydieresis +ENCODING 255 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +00 +88 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR Amacron +ENCODING 256 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F8 +00 +70 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR amacron +ENCODING 257 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR Abreve +ENCODING 258 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +88 +70 +00 +70 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR abreve +ENCODING 259 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +88 +70 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR Aogonek +ENCODING 260 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +50 +88 +88 +F8 +88 +88 +10 +18 +00 +ENDCHAR +STARTCHAR aogonek +ENCODING 261 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +88 +88 +98 +68 +10 +08 +00 +ENDCHAR +STARTCHAR Cacute +ENCODING 262 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +70 +88 +88 +80 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR cacute +ENCODING 263 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +78 +80 +80 +80 +78 +00 +00 +00 +ENDCHAR +STARTCHAR Ccircumflex +ENCODING 264 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +00 +70 +88 +88 +80 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR ccircumflex +ENCODING 265 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +00 +78 +80 +80 +80 +78 +00 +00 +00 +ENDCHAR +STARTCHAR Cdotaccent +ENCODING 266 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +70 +88 +88 +80 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR cdotaccent +ENCODING 267 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +00 +78 +80 +80 +80 +78 +00 +00 +00 +ENDCHAR +STARTCHAR Ccaron +ENCODING 268 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +00 +70 +88 +88 +80 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR ccaron +ENCODING 269 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +20 +00 +78 +80 +80 +80 +78 +00 +00 +00 +ENDCHAR +STARTCHAR Dcaron +ENCODING 270 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +00 +E0 +90 +88 +88 +90 +E0 +00 +00 +00 +ENDCHAR +STARTCHAR dcaron +ENCODING 271 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +08 +08 +78 +88 +88 +88 +78 +00 +00 +00 +ENDCHAR +STARTCHAR Dcroat +ENCODING 272 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +48 +44 +E4 +44 +48 +70 +00 +00 +00 +ENDCHAR +STARTCHAR dcroat +ENCODING 273 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +38 +10 +70 +90 +90 +90 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Emacron +ENCODING 274 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F8 +00 +F8 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR emacron +ENCODING 275 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Ebreve +ENCODING 276 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +88 +70 +00 +F8 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR ebreve +ENCODING 277 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +88 +70 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Edotaccent +ENCODING 278 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +F8 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR edotaccent +ENCODING 279 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Eogonek +ENCODING 280 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F8 +80 +F0 +80 +80 +F8 +20 +10 +00 +ENDCHAR +STARTCHAR eogonek +ENCODING 281 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +F8 +80 +70 +40 +20 +00 +ENDCHAR +STARTCHAR Ecaron +ENCODING 282 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +00 +F8 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR ecaron +ENCODING 283 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +20 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Gcircumflex +ENCODING 284 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +00 +70 +88 +80 +98 +88 +78 +00 +00 +00 +ENDCHAR +STARTCHAR gcircumflex +ENCODING 285 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +00 +78 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR Gbreve +ENCODING 286 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +88 +70 +00 +70 +88 +80 +98 +88 +78 +00 +00 +00 +ENDCHAR +STARTCHAR gbreve +ENCODING 287 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +88 +70 +00 +78 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR Gdotaccent +ENCODING 288 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +70 +88 +80 +98 +88 +78 +00 +00 +00 +ENDCHAR +STARTCHAR gdotaccent +ENCODING 289 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +00 +78 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR Gcommaaccent +ENCODING 290 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +98 +88 +88 +78 +20 +40 +00 +ENDCHAR +STARTCHAR gcommaaccent +ENCODING 291 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +30 +00 +78 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR Hcircumflex +ENCODING 292 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +00 +88 +88 +F8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR hcircumflex +ENCODING 293 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +00 +80 +80 +F0 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Hbar +ENCODING 294 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +48 +FC +48 +78 +48 +48 +48 +00 +00 +00 +ENDCHAR +STARTCHAR hbar +ENCODING 295 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +F8 +40 +78 +44 +44 +44 +44 +00 +00 +00 +ENDCHAR +STARTCHAR Itilde +ENCODING 296 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +28 +50 +00 +F8 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR itilde +ENCODING 297 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +28 +50 +00 +30 +10 +10 +10 +38 +00 +00 +00 +ENDCHAR +STARTCHAR Imacron +ENCODING 298 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F8 +00 +F8 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR imacron +ENCODING 299 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Ibreve +ENCODING 300 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +88 +70 +00 +F8 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR ibreve +ENCODING 301 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +88 +70 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Iogonek +ENCODING 302 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +20 +20 +20 +F8 +20 +10 +00 +ENDCHAR +STARTCHAR iogonek +ENCODING 303 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +00 +60 +20 +20 +20 +70 +20 +10 +00 +ENDCHAR +STARTCHAR Idotaccent +ENCODING 304 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +F8 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR dotlessi +ENCODING 305 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR IJ +ENCODING 306 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +88 +88 +88 +A8 +A8 +90 +00 +00 +00 +ENDCHAR +STARTCHAR ij +ENCODING 307 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +48 +00 +D8 +48 +48 +48 +E8 +08 +48 +30 +ENDCHAR +STARTCHAR Jcircumflex +ENCODING 308 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +28 +00 +38 +08 +08 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR jcircumflex +ENCODING 309 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +28 +00 +70 +10 +10 +10 +10 +10 +10 +E0 +ENDCHAR +STARTCHAR Kcommaaccent +ENCODING 310 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +90 +A0 +C0 +A0 +90 +88 +40 +C0 +00 +ENDCHAR +STARTCHAR kcommaaccent +ENCODING 311 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +40 +40 +48 +50 +60 +50 +48 +20 +60 +00 +ENDCHAR +STARTCHAR kgreenlandic +ENCODING 312 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +90 +E0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Lacute +ENCODING 313 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +40 +00 +80 +80 +80 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR lacute +ENCODING 314 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +20 +20 +20 +20 +20 +10 +00 +00 +00 +ENDCHAR +STARTCHAR Lcommaaccent +ENCODING 315 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +80 +80 +80 +80 +80 +80 +F8 +20 +40 +00 +ENDCHAR +STARTCHAR lcommaaccent +ENCODING 316 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +60 +20 +20 +20 +20 +20 +20 +70 +20 +40 +00 +ENDCHAR +STARTCHAR Lcaron +ENCODING 317 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +80 +80 +80 +80 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR lcaron +ENCODING 318 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +00 +20 +20 +20 +20 +20 +10 +00 +00 +00 +ENDCHAR +STARTCHAR Ldot +ENCODING 319 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +80 +80 +80 +90 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR ldot +ENCODING 320 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +C0 +40 +40 +40 +48 +40 +40 +E0 +00 +00 +00 +ENDCHAR +STARTCHAR Lslash +ENCODING 321 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +40 +40 +60 +C0 +40 +40 +7C +00 +00 +00 +ENDCHAR +STARTCHAR lslash +ENCODING 322 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +60 +20 +20 +30 +60 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Nacute +ENCODING 323 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +88 +C8 +A8 +98 +98 +88 +00 +00 +00 +ENDCHAR +STARTCHAR nacute +ENCODING 324 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +B0 +C8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Ncommaaccent +ENCODING 325 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +C8 +C8 +A8 +98 +98 +88 +40 +C0 +00 +ENDCHAR +STARTCHAR ncommaaccent +ENCODING 326 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +B0 +C8 +88 +88 +88 +40 +C0 +00 +ENDCHAR +STARTCHAR Ncaron +ENCODING 327 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +00 +88 +C8 +A8 +98 +98 +88 +00 +00 +00 +ENDCHAR +STARTCHAR ncaron +ENCODING 328 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +20 +00 +B0 +C8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR napostrophe +ENCODING 329 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +C0 +40 +80 +00 +B0 +C8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Eng +ENCODING 330 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +C8 +C8 +A8 +98 +98 +88 +08 +30 +00 +ENDCHAR +STARTCHAR eng +ENCODING 331 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +B0 +C8 +88 +88 +88 +08 +30 +00 +ENDCHAR +STARTCHAR Omacron +ENCODING 332 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F8 +00 +70 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR omacron +ENCODING 333 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Obreve +ENCODING 334 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +88 +70 +00 +70 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR obreve +ENCODING 335 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +88 +70 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Ohungarumlaut +ENCODING 336 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +48 +90 +00 +70 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR ohungarumlaut +ENCODING 337 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +48 +90 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR OE +ENCODING 338 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +78 +A0 +A0 +B0 +A0 +A0 +78 +00 +00 +00 +ENDCHAR +STARTCHAR oe +ENCODING 339 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +A8 +B8 +A0 +78 +00 +00 +00 +ENDCHAR +STARTCHAR Racute +ENCODING 340 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +F0 +88 +F0 +A0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR racute +ENCODING 341 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +58 +60 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR Rcommaaccent +ENCODING 342 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +88 +88 +F0 +A0 +90 +88 +40 +C0 +00 +ENDCHAR +STARTCHAR rcommaaccent +ENCODING 343 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +58 +60 +40 +40 +40 +20 +60 +00 +ENDCHAR +STARTCHAR Rcaron +ENCODING 344 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +00 +F0 +88 +F0 +A0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR rcaron +ENCODING 345 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +28 +10 +00 +58 +60 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR Sacute +ENCODING 346 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +70 +80 +70 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR sacute +ENCODING 347 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +78 +80 +70 +08 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR Scircumflex +ENCODING 348 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +00 +70 +80 +70 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR scircumflex +ENCODING 349 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +00 +78 +80 +70 +08 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR Scedilla +ENCODING 350 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +70 +08 +88 +70 +20 +60 +00 +ENDCHAR +STARTCHAR scedilla +ENCODING 351 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +80 +70 +08 +F0 +20 +60 +00 +ENDCHAR +STARTCHAR Scaron +ENCODING 352 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +00 +70 +80 +70 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR scaron +ENCODING 353 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +20 +00 +78 +80 +70 +08 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR Tcommaaccent +ENCODING 354 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +20 +20 +20 +20 +10 +30 +00 +ENDCHAR +STARTCHAR tcommaaccent +ENCODING 355 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +20 +F8 +20 +20 +20 +18 +10 +30 +00 +ENDCHAR +STARTCHAR Tcaron +ENCODING 356 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +00 +F8 +20 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR tcaron +ENCODING 357 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +00 +20 +20 +F8 +20 +20 +18 +00 +00 +00 +ENDCHAR +STARTCHAR Tbar +ENCODING 358 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +70 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR tbar +ENCODING 359 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +20 +F8 +20 +70 +20 +18 +00 +00 +00 +ENDCHAR +STARTCHAR Utilde +ENCODING 360 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +28 +50 +00 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR utilde +ENCODING 361 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +28 +50 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR Umacron +ENCODING 362 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F8 +00 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR umacron +ENCODING 363 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR Ubreve +ENCODING 364 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +88 +70 +00 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR ubreve +ENCODING 365 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +88 +70 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR Uring +ENCODING 366 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +20 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uring +ENCODING 367 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +20 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR Uhungarumlaut +ENCODING 368 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +48 +90 +00 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uhungarumlaut +ENCODING 369 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +48 +90 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR Uogonek +ENCODING 370 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +88 +88 +88 +88 +88 +70 +40 +20 +00 +ENDCHAR +STARTCHAR uogonek +ENCODING 371 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +88 +98 +68 +10 +08 +00 +ENDCHAR +STARTCHAR Wcircumflex +ENCODING 372 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +00 +88 +88 +A8 +A8 +D8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR wcircumflex +ENCODING 373 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +00 +88 +A8 +A8 +A8 +50 +00 +00 +00 +ENDCHAR +STARTCHAR Ycircumflex +ENCODING 374 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +00 +88 +50 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR ycircumflex +ENCODING 375 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +00 +88 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR Ydieresis +ENCODING 376 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +00 +88 +50 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR Zacute +ENCODING 377 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +F8 +10 +20 +40 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR zacute +ENCODING 378 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +F8 +10 +20 +40 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Zdotaccent +ENCODING 379 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +F8 +10 +20 +40 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR zdotaccent +ENCODING 380 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +00 +F8 +10 +20 +40 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Zcaron +ENCODING 381 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +00 +F8 +10 +20 +40 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR zcaron +ENCODING 382 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +20 +00 +F8 +10 +20 +40 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR longs +ENCODING 383 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +18 +20 +20 +60 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni0180 +ENCODING 384 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +E0 +40 +78 +44 +44 +44 +78 +00 +00 +00 +ENDCHAR +STARTCHAR uni0181 +ENCODING 385 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +48 +48 +70 +48 +48 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni0182 +ENCODING 386 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +40 +40 +70 +48 +48 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR uni0183 +ENCODING 387 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +80 +80 +F0 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni0184 +ENCODING 388 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +60 +E0 +78 +24 +24 +24 +78 +00 +00 +00 +ENDCHAR +STARTCHAR uni0185 +ENCODING 389 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +C0 +C0 +70 +48 +48 +48 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni0186 +ENCODING 390 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +08 +08 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni0187 +ENCODING 391 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +18 +70 +88 +80 +80 +80 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni0188 +ENCODING 392 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +10 +68 +80 +80 +80 +60 +00 +00 +00 +ENDCHAR +STARTCHAR uni0189 +ENCODING 393 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +48 +44 +E4 +44 +48 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni018A +ENCODING 394 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +E0 +50 +48 +48 +48 +50 +60 +00 +00 +00 +ENDCHAR +STARTCHAR uni018B +ENCODING 395 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +78 +08 +08 +78 +88 +88 +88 +78 +00 +00 +00 +ENDCHAR +STARTCHAR uni018C +ENCODING 396 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +78 +08 +08 +78 +88 +88 +88 +78 +00 +00 +00 +ENDCHAR +STARTCHAR uni018D +ENCODING 397 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +88 +88 +70 +50 +20 +00 +ENDCHAR +STARTCHAR uni018E +ENCODING 398 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +08 +08 +78 +08 +08 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni018F +ENCODING 399 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +08 +F8 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni0190 +ENCODING 400 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +60 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni0191 +ENCODING 401 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +40 +40 +70 +40 +40 +40 +40 +80 +00 +ENDCHAR +STARTCHAR florin +ENCODING 402 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +38 +40 +40 +F0 +40 +40 +40 +40 +40 +80 +00 +ENDCHAR +STARTCHAR uni0193 +ENCODING 403 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +08 +70 +90 +80 +98 +88 +88 +78 +00 +00 +00 +ENDCHAR +STARTCHAR uni0194 +ENCODING 404 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +50 +50 +20 +20 +50 +20 +ENDCHAR +STARTCHAR uni0195 +ENCODING 405 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +80 +80 +C8 +A8 +A8 +A8 +90 +00 +00 +00 +ENDCHAR +STARTCHAR uni0196 +ENCODING 406 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +60 +20 +20 +20 +20 +28 +10 +00 +00 +00 +ENDCHAR +STARTCHAR uni0197 +ENCODING 407 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +70 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni0198 +ENCODING 408 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +90 +A8 +A8 +C0 +A0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR uni0199 +ENCODING 409 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +40 +48 +50 +60 +50 +48 +00 +00 +00 +ENDCHAR +STARTCHAR uni019A +ENCODING 410 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +60 +20 +20 +F8 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni019B +ENCODING 411 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +68 +30 +60 +A0 +50 +50 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR uni019C +ENCODING 412 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +A8 +A8 +A8 +58 +00 +00 +00 +ENDCHAR +STARTCHAR uni019D +ENCODING 413 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +44 +64 +64 +54 +4C +4C +44 +40 +80 +00 +ENDCHAR +STARTCHAR uni019E +ENCODING 414 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +B0 +C8 +88 +88 +88 +08 +08 +00 +ENDCHAR +STARTCHAR uni019F +ENCODING 415 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +88 +F8 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Ohorn +ENCODING 416 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +18 +08 +10 +70 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR ohorn +ENCODING 417 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +18 +08 +10 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni01A2 +ENCODING 418 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +40 +B0 +A8 +A8 +A8 +A8 +48 +08 +08 +00 +ENDCHAR +STARTCHAR uni01A3 +ENCODING 419 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +50 +A8 +A8 +A8 +48 +08 +08 +00 +ENDCHAR +STARTCHAR uni01A4 +ENCODING 420 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +48 +48 +70 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR uni01A5 +ENCODING 421 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +08 +10 +F0 +88 +88 +88 +F0 +80 +80 +80 +ENDCHAR +STARTCHAR uni01A6 +ENCODING 422 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +80 +F0 +88 +F0 +A0 +90 +88 +08 +00 +00 +ENDCHAR +STARTCHAR uni01A7 +ENCODING 423 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +08 +70 +80 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni01A8 +ENCODING 424 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F0 +08 +70 +80 +78 +00 +00 +00 +ENDCHAR +STARTCHAR uni01A9 +ENCODING 425 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +40 +20 +10 +20 +40 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni01AA +ENCODING 426 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +30 +10 +10 +10 +10 +10 +10 +10 +08 +00 +ENDCHAR +STARTCHAR uni01AB +ENCODING 427 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +20 +F8 +20 +20 +20 +18 +10 +60 +00 +ENDCHAR +STARTCHAR uni01AC +ENCODING 428 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +78 +A0 +A0 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni01AD +ENCODING 429 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +48 +40 +E0 +40 +40 +40 +30 +00 +00 +00 +ENDCHAR +STARTCHAR uni01AE +ENCODING 430 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +20 +20 +20 +20 +20 +18 +00 +ENDCHAR +STARTCHAR Uhorn +ENCODING 431 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +18 +08 +10 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uhorn +ENCODING 432 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +18 +08 +10 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR uni01B1 +ENCODING 433 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +50 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni01B2 +ENCODING 434 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +90 +88 +88 +88 +90 +90 +60 +00 +00 +00 +ENDCHAR +STARTCHAR uni01B3 +ENCODING 435 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +44 +A8 +10 +10 +10 +10 +10 +00 +00 +00 +ENDCHAR +STARTCHAR uni01B4 +ENCODING 436 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +08 +90 +90 +90 +90 +70 +10 +10 +60 +ENDCHAR +STARTCHAR uni01B5 +ENCODING 437 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +08 +10 +F8 +40 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni01B6 +ENCODING 438 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F8 +10 +F8 +40 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni01B7 +ENCODING 439 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +08 +10 +20 +70 +08 +08 +90 +60 +00 +ENDCHAR +STARTCHAR uni01B8 +ENCODING 440 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +80 +40 +20 +70 +80 +80 +48 +30 +00 +ENDCHAR +STARTCHAR uni01B9 +ENCODING 441 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F8 +40 +20 +70 +80 +80 +78 +00 +ENDCHAR +STARTCHAR uni01BA +ENCODING 442 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F8 +40 +20 +70 +80 +80 +88 +70 +ENDCHAR +STARTCHAR uni01BB +ENCODING 443 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +08 +10 +F8 +40 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni01BC +ENCODING 444 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +78 +48 +20 +10 +08 +08 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni01BD +ENCODING 445 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +40 +30 +08 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni01BE +ENCODING 446 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +70 +20 +30 +08 +48 +30 +00 +00 +00 +ENDCHAR +STARTCHAR uni01BF +ENCODING 447 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +10 +28 +48 +48 +50 +60 +40 +40 +ENDCHAR +STARTCHAR uni01C0 +ENCODING 448 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +20 +20 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni01C1 +ENCODING 449 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +50 +50 +50 +50 +50 +50 +00 +00 +00 +ENDCHAR +STARTCHAR uni01C2 +ENCODING 450 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +20 +70 +20 +70 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni01C3 +ENCODING 451 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +70 +70 +20 +20 +00 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni01C4 +ENCODING 452 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +14 +08 +DC +A4 +A4 +A8 +B0 +B0 +DC +00 +00 +00 +ENDCHAR +STARTCHAR uni01C5 +ENCODING 453 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +14 +C8 +A0 +BC +A4 +A8 +B0 +DC +00 +00 +00 +ENDCHAR +STARTCHAR uni01C6 +ENCODING 454 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +14 +28 +20 +7C +A4 +A8 +B0 +7C +00 +00 +00 +ENDCHAR +STARTCHAR uni01C7 +ENCODING 455 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +84 +84 +84 +84 +84 +94 +E8 +00 +00 +00 +ENDCHAR +STARTCHAR uni01C8 +ENCODING 456 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +84 +80 +84 +84 +84 +84 +E4 +04 +24 +18 +ENDCHAR +STARTCHAR uni01C9 +ENCODING 457 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +48 +40 +48 +48 +48 +48 +28 +08 +30 +00 +ENDCHAR +STARTCHAR uni01CA +ENCODING 458 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +94 +94 +D4 +B4 +94 +94 +94 +04 +18 +00 +ENDCHAR +STARTCHAR uni01CB +ENCODING 459 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +94 +90 +D4 +B4 +94 +94 +94 +04 +18 +00 +ENDCHAR +STARTCHAR uni01CC +ENCODING 460 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +08 +00 +C8 +A8 +A8 +A8 +A8 +08 +30 +00 +ENDCHAR +STARTCHAR uni01CD +ENCODING 461 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +00 +70 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR uni01CE +ENCODING 462 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +20 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR uni01CF +ENCODING 463 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +28 +50 +00 +F8 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni01D0 +ENCODING 464 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +28 +50 +00 +30 +10 +10 +10 +38 +00 +00 +00 +ENDCHAR +STARTCHAR uni01D1 +ENCODING 465 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F8 +00 +70 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni01D2 +ENCODING 466 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni01D3 +ENCODING 467 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +48 +90 +00 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni01D4 +ENCODING 468 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +48 +90 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR uni01D5 +ENCODING 469 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +F8 +00 +50 +00 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni01D6 +ENCODING 470 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +F8 +00 +50 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR uni01D7 +ENCODING 471 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +50 +00 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni01D8 +ENCODING 472 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +50 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR uni01D9 +ENCODING 473 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +50 +00 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni01DA +ENCODING 474 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +50 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR uni01DB +ENCODING 475 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +50 +00 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni01DC +ENCODING 476 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +50 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR uni01DD +ENCODING 477 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +08 +F8 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni01DE +ENCODING 478 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +F8 +00 +50 +00 +70 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR uni01DF +ENCODING 479 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +F8 +00 +50 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR uni01E0 +ENCODING 480 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +F8 +00 +20 +00 +70 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR uni01E1 +ENCODING 481 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +F8 +00 +20 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR uni01E2 +ENCODING 482 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +F8 +00 +78 +A0 +A0 +B8 +E0 +A0 +B8 +00 +00 +00 +ENDCHAR +STARTCHAR uni01E3 +ENCODING 483 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +78 +00 +70 +28 +70 +A0 +78 +00 +00 +00 +ENDCHAR +STARTCHAR uni01E4 +ENCODING 484 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +80 +90 +90 +B8 +90 +60 +00 +00 +00 +ENDCHAR +STARTCHAR uni01E5 +ENCODING 485 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +90 +B8 +90 +70 +10 +10 +60 +ENDCHAR +STARTCHAR Gcaron +ENCODING 486 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +00 +70 +88 +80 +98 +88 +78 +00 +00 +00 +ENDCHAR +STARTCHAR gcaron +ENCODING 487 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +20 +00 +78 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR uni01E8 +ENCODING 488 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +88 +90 +A0 +C0 +A0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR uni01E9 +ENCODING 489 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +28 +10 +40 +40 +48 +50 +60 +50 +48 +00 +00 +00 +ENDCHAR +STARTCHAR uni01EA +ENCODING 490 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +88 +88 +88 +88 +70 +40 +60 +00 +ENDCHAR +STARTCHAR uni01EB +ENCODING 491 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +88 +88 +70 +40 +60 +00 +ENDCHAR +STARTCHAR uni01EC +ENCODING 492 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F8 +00 +70 +88 +88 +88 +88 +70 +40 +60 +00 +ENDCHAR +STARTCHAR uni01ED +ENCODING 493 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +00 +70 +88 +88 +88 +70 +40 +60 +00 +ENDCHAR +STARTCHAR uni01EE +ENCODING 494 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +00 +F8 +10 +20 +70 +08 +08 +90 +60 +00 +ENDCHAR +STARTCHAR uni01EF +ENCODING 495 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +20 +00 +F8 +10 +20 +70 +08 +08 +F0 +00 +ENDCHAR +STARTCHAR uni01F0 +ENCODING 496 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +28 +10 +00 +70 +10 +10 +10 +10 +10 +10 +E0 +ENDCHAR +STARTCHAR uni01F1 +ENCODING 497 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +DC +A4 +A4 +A8 +B0 +B0 +DC +00 +00 +00 +ENDCHAR +STARTCHAR uni01F2 +ENCODING 498 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +04 +C0 +A0 +BC +A4 +A8 +B0 +DC +00 +00 +00 +ENDCHAR +STARTCHAR uni01F3 +ENCODING 499 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +20 +7C +A4 +A8 +B0 +7C +00 +00 +00 +ENDCHAR +STARTCHAR uni01F4 +ENCODING 500 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +70 +80 +80 +98 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni01F5 +ENCODING 501 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +78 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR Aringacute +ENCODING 506 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +20 +50 +20 +70 +88 +F8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR aringacute +ENCODING 507 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +20 +50 +20 +00 +78 +88 +78 +00 +00 +00 +ENDCHAR +STARTCHAR AEacute +ENCODING 508 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +78 +A0 +B8 +E0 +A0 +B8 +00 +00 +00 +ENDCHAR +STARTCHAR aeacute +ENCODING 509 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +70 +28 +70 +A0 +78 +00 +00 +00 +ENDCHAR +STARTCHAR Oslashacute +ENCODING 510 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +08 +78 +98 +A8 +A8 +C8 +F0 +80 +00 +00 +ENDCHAR +STARTCHAR oslashacute +ENCODING 511 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +08 +78 +98 +A8 +C8 +F0 +80 +00 +00 +ENDCHAR +STARTCHAR uni0200 +ENCODING 512 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +90 +48 +00 +70 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR uni0201 +ENCODING 513 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +90 +48 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR uni0202 +ENCODING 514 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +70 +88 +00 +70 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR uni0203 +ENCODING 515 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +00 +78 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR uni0204 +ENCODING 516 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +90 +48 +00 +F8 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni0205 +ENCODING 517 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +90 +48 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni0206 +ENCODING 518 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +70 +88 +00 +F8 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni0207 +ENCODING 519 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni0208 +ENCODING 520 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +90 +48 +00 +F8 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni0209 +ENCODING 521 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +90 +48 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni020A +ENCODING 522 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +70 +88 +00 +F8 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni020B +ENCODING 523 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni020C +ENCODING 524 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +90 +48 +00 +70 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni020D +ENCODING 525 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +90 +48 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni020E +ENCODING 526 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +70 +88 +00 +70 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni020F +ENCODING 527 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni0210 +ENCODING 528 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +90 +48 +00 +F0 +88 +F0 +A0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR uni0211 +ENCODING 529 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +90 +48 +00 +B0 +C0 +80 +80 +80 +00 +00 +00 +ENDCHAR +STARTCHAR uni0212 +ENCODING 530 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +70 +88 +00 +F0 +88 +F0 +A0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR uni0213 +ENCODING 531 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +00 +B0 +C0 +80 +80 +80 +00 +00 +00 +ENDCHAR +STARTCHAR uni0214 +ENCODING 532 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +90 +48 +00 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni0215 +ENCODING 533 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +90 +48 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR uni0216 +ENCODING 534 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +70 +88 +00 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni0217 +ENCODING 535 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +00 +88 +88 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR Scommaaccent +ENCODING 536 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +70 +08 +88 +70 +60 +20 +40 +ENDCHAR +STARTCHAR scommaaccent +ENCODING 537 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +80 +70 +08 +F0 +60 +20 +40 +ENDCHAR +STARTCHAR Tcommaaccent +ENCODING 538 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +20 +20 +20 +20 +30 +10 +20 +ENDCHAR +STARTCHAR tcommaaccent +ENCODING 539 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +20 +F8 +20 +20 +20 +18 +30 +10 +20 +ENDCHAR +STARTCHAR uni0259 +ENCODING 601 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +08 +F8 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni02BB +ENCODING 699 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +30 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR afii57929 +ENCODING 700 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +10 +20 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR afii64937 +ENCODING 701 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +20 +10 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni02BE +ENCODING 702 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +10 +10 +20 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni02BF +ENCODING 703 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +20 +10 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR circumflex +ENCODING 710 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR caron +ENCODING 711 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR macron +ENCODING 713 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni02D6 +ENCODING 726 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +70 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR breve +ENCODING 728 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +48 +30 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR dotaccent +ENCODING 729 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR ring +ENCODING 730 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR ogonek +ENCODING 731 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +20 +40 +30 +ENDCHAR +STARTCHAR tilde +ENCODING 732 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +28 +50 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR hungarumlaut +ENCODING 733 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +48 +90 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR gravecomb +ENCODING 768 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +10 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR acutecomb +ENCODING 769 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni0302 +ENCODING 770 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR tildecomb +ENCODING 771 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +28 +50 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni0304 +ENCODING 772 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni0305 +ENCODING 773 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F8 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni0306 +ENCODING 774 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +88 +70 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni0307 +ENCODING 775 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni0308 +ENCODING 776 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR hookabovecomb +ENCODING 777 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +60 +10 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni030A +ENCODING 778 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni030B +ENCODING 779 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +48 +90 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni030C +ENCODING 780 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni030D +ENCODING 781 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni030E +ENCODING 782 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +50 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni030F +ENCODING 783 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +90 +48 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni0310 +ENCODING 784 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +88 +70 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni0311 +ENCODING 785 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +70 +88 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni0338 +ENCODING 824 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +08 +08 +10 +10 +20 +40 +40 +80 +80 +00 +00 +ENDCHAR +STARTCHAR uni0374 +ENCODING 884 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni0375 +ENCODING 885 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +10 +20 +00 +ENDCHAR +STARTCHAR uni037A +ENCODING 890 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +20 +30 +ENDCHAR +STARTCHAR uni037E +ENCODING 894 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +30 +30 +00 +00 +30 +30 +20 +40 +00 +ENDCHAR +STARTCHAR tonos +ENCODING 900 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR dieresistonos +ENCODING 901 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +50 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR Alphatonos +ENCODING 902 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +90 +28 +44 +44 +7C +44 +44 +00 +00 +00 +ENDCHAR +STARTCHAR anoteleia +ENCODING 903 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +30 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR Epsilontonos +ENCODING 904 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +BC +20 +20 +38 +20 +20 +3C +00 +00 +00 +ENDCHAR +STARTCHAR Etatonos +ENCODING 905 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +A4 +24 +24 +3C +24 +24 +24 +00 +00 +00 +ENDCHAR +STARTCHAR Iotatonos +ENCODING 906 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +B8 +10 +10 +10 +10 +10 +38 +00 +00 +00 +ENDCHAR +STARTCHAR Omicrontonos +ENCODING 908 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +98 +24 +24 +24 +24 +24 +18 +00 +00 +00 +ENDCHAR +STARTCHAR Upsilontonos +ENCODING 910 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +A8 +28 +10 +10 +10 +10 +10 +00 +00 +00 +ENDCHAR +STARTCHAR Omegatonos +ENCODING 911 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +90 +28 +44 +44 +44 +28 +6C +00 +00 +00 +ENDCHAR +STARTCHAR iotadieresistonos +ENCODING 912 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +50 +00 +60 +20 +28 +10 +00 +00 +00 +ENDCHAR +STARTCHAR Alpha +ENCODING 913 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +50 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Beta +ENCODING 914 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +88 +88 +F0 +88 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR Gamma +ENCODING 915 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +78 +40 +40 +40 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR Delta +ENCODING 916 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +50 +50 +50 +88 +88 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Epsilon +ENCODING 917 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +80 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Zeta +ENCODING 918 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +08 +10 +20 +40 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Eta +ENCODING 919 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +F8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Theta +ENCODING 920 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +88 +A8 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Iota +ENCODING 921 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Kappa +ENCODING 922 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +90 +A0 +C0 +A0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Lambda +ENCODING 923 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +20 +50 +50 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Mu +ENCODING 924 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +D8 +A8 +A8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Nu +ENCODING 925 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +C8 +C8 +A8 +98 +98 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Xi +ENCODING 926 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +00 +00 +70 +00 +00 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Omicron +ENCODING 927 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Pi +ENCODING 928 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +88 +88 +88 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Rho +ENCODING 929 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +88 +88 +F0 +80 +80 +80 +00 +00 +00 +ENDCHAR +STARTCHAR Sigma +ENCODING 931 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +40 +20 +10 +20 +40 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Tau +ENCODING 932 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR Upsilon +ENCODING 933 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +50 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR Phi +ENCODING 934 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +20 +70 +A8 +A8 +70 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR Chi +ENCODING 935 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +50 +20 +50 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR Psi +ENCODING 936 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +A8 +A8 +A8 +70 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR Omega +ENCODING 937 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +88 +88 +88 +50 +D8 +00 +00 +00 +ENDCHAR +STARTCHAR Iotadieresis +ENCODING 938 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +00 +F8 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Upsilondieresis +ENCODING 939 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +00 +88 +50 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR alphatonos +ENCODING 940 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +00 +68 +98 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR epsilontonos +ENCODING 941 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +00 +70 +88 +60 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR etatonos +ENCODING 942 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +00 +B0 +C8 +88 +88 +88 +08 +08 +00 +ENDCHAR +STARTCHAR iotatonos +ENCODING 943 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +00 +60 +20 +20 +28 +10 +00 +00 +00 +ENDCHAR +STARTCHAR upsilondieresistonos +ENCODING 944 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +88 +00 +90 +88 +88 +90 +60 +00 +00 +00 +ENDCHAR +STARTCHAR alpha +ENCODING 945 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +68 +98 +88 +98 +68 +00 +00 +00 +ENDCHAR +STARTCHAR beta +ENCODING 946 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +88 +F0 +88 +88 +C8 +B0 +80 +00 +ENDCHAR +STARTCHAR gamma +ENCODING 947 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +44 +A8 +28 +10 +10 +10 +10 +00 +00 +00 +ENDCHAR +STARTCHAR delta +ENCODING 948 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +48 +20 +10 +30 +48 +48 +48 +30 +00 +00 +00 +ENDCHAR +STARTCHAR epsilon +ENCODING 949 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +60 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR zeta +ENCODING 950 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +38 +20 +40 +40 +40 +40 +38 +08 +30 +00 +ENDCHAR +STARTCHAR eta +ENCODING 951 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +B0 +C8 +88 +88 +88 +08 +08 +00 +ENDCHAR +STARTCHAR theta +ENCODING 952 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +30 +48 +48 +78 +48 +48 +30 +00 +00 +00 +ENDCHAR +STARTCHAR iota +ENCODING 953 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +60 +20 +20 +28 +10 +00 +00 +00 +ENDCHAR +STARTCHAR kappa +ENCODING 954 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +48 +50 +60 +50 +48 +00 +00 +00 +ENDCHAR +STARTCHAR lambda +ENCODING 955 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +A0 +20 +20 +50 +50 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR mu +ENCODING 956 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +88 +98 +E8 +80 +80 +00 +ENDCHAR +STARTCHAR nu +ENCODING 957 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +D8 +50 +50 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR xi +ENCODING 958 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +70 +80 +80 +70 +80 +80 +70 +08 +30 +00 +ENDCHAR +STARTCHAR omicron +ENCODING 959 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR pi +ENCODING 960 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F8 +88 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR rho +ENCODING 961 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +88 +88 +B0 +80 +80 +80 +ENDCHAR +STARTCHAR sigma1 +ENCODING 962 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +80 +70 +08 +70 +00 +00 +00 +ENDCHAR +STARTCHAR sigma +ENCODING 963 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +90 +90 +90 +60 +00 +00 +00 +ENDCHAR +STARTCHAR tau +ENCODING 964 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +20 +20 +28 +10 +00 +00 +00 +ENDCHAR +STARTCHAR upsilon +ENCODING 965 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +90 +88 +88 +88 +90 +60 +00 +00 +00 +ENDCHAR +STARTCHAR phi +ENCODING 966 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +30 +A8 +A8 +A8 +70 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR chi +ENCODING 967 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +50 +20 +50 +88 +00 +00 +00 +ENDCHAR +STARTCHAR psi +ENCODING 968 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +A8 +A8 +70 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR omega +ENCODING 969 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +50 +88 +A8 +A8 +50 +00 +00 +00 +ENDCHAR +STARTCHAR iotadieresis +ENCODING 970 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +00 +60 +20 +20 +28 +10 +00 +00 +00 +ENDCHAR +STARTCHAR upsilondieresis +ENCODING 971 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +00 +90 +88 +88 +88 +90 +60 +00 +00 +00 +ENDCHAR +STARTCHAR omicrontonos +ENCODING 972 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR upsilontonos +ENCODING 973 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +00 +90 +88 +88 +88 +90 +60 +00 +00 +00 +ENDCHAR +STARTCHAR omegatonos +ENCODING 974 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +00 +50 +88 +A8 +A8 +50 +00 +00 +00 +ENDCHAR +STARTCHAR theta1 +ENCODING 977 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +60 +90 +90 +78 +10 +90 +90 +60 +00 +00 +00 +ENDCHAR +STARTCHAR phi1 +ENCODING 981 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +20 +70 +A8 +A8 +A8 +70 +20 +20 +00 +ENDCHAR +STARTCHAR omega1 +ENCODING 982 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +FC +44 +54 +54 +28 +00 +00 +00 +ENDCHAR +STARTCHAR uni03F1 +ENCODING 1009 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +30 +48 +48 +48 +70 +40 +38 +00 +ENDCHAR +STARTCHAR afii10023 +ENCODING 1025 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +00 +F8 +80 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10051 +ENCODING 1026 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +E0 +40 +40 +70 +48 +48 +48 +08 +30 +00 +ENDCHAR +STARTCHAR afii10052 +ENCODING 1027 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +78 +40 +40 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR afii10053 +ENCODING 1028 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +F0 +80 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10054 +ENCODING 1029 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +70 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10055 +ENCODING 1030 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10056 +ENCODING 1031 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +00 +F8 +20 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10057 +ENCODING 1032 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +38 +08 +08 +08 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10058 +ENCODING 1033 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +60 +A0 +A0 +B0 +A8 +A8 +A8 +B0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10059 +ENCODING 1034 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +A0 +A0 +A0 +F0 +A8 +A8 +A8 +B0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10060 +ENCODING 1035 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +E0 +40 +40 +70 +48 +48 +48 +00 +00 +00 +ENDCHAR +STARTCHAR afii10061 +ENCODING 1036 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +88 +90 +E0 +90 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10062 +ENCODING 1038 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +88 +70 +00 +88 +88 +88 +78 +08 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10145 +ENCODING 1039 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +88 +88 +88 +F8 +20 +20 +00 +ENDCHAR +STARTCHAR afii10017 +ENCODING 1040 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +50 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10018 +ENCODING 1041 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +80 +80 +F0 +88 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10019 +ENCODING 1042 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +88 +88 +F0 +88 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10020 +ENCODING 1043 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +78 +40 +40 +40 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR afii10021 +ENCODING 1044 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +30 +50 +50 +50 +50 +50 +F8 +88 +00 +00 +ENDCHAR +STARTCHAR afii10022 +ENCODING 1045 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +80 +80 +F0 +80 +80 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10024 +ENCODING 1046 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +A8 +A8 +A8 +70 +A8 +A8 +A8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10025 +ENCODING 1047 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +88 +08 +10 +08 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10026 +ENCODING 1048 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +98 +98 +A8 +C8 +C8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10027 +ENCODING 1049 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +88 +70 +88 +98 +98 +A8 +C8 +C8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10028 +ENCODING 1050 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +90 +A0 +C0 +A0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10029 +ENCODING 1051 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +38 +48 +48 +48 +48 +48 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10030 +ENCODING 1052 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +D8 +A8 +A8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10031 +ENCODING 1053 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +F8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10032 +ENCODING 1054 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10033 +ENCODING 1055 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +88 +88 +88 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10034 +ENCODING 1056 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +88 +88 +F0 +80 +80 +80 +00 +00 +00 +ENDCHAR +STARTCHAR afii10035 +ENCODING 1057 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +80 +80 +80 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10036 +ENCODING 1058 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR afii10037 +ENCODING 1059 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +78 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10038 +ENCODING 1060 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +20 +70 +A8 +A8 +70 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10039 +ENCODING 1061 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +50 +20 +50 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10040 +ENCODING 1062 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +90 +90 +90 +90 +90 +90 +F8 +08 +00 +00 +ENDCHAR +STARTCHAR afii10041 +ENCODING 1063 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +78 +08 +08 +08 +00 +00 +00 +ENDCHAR +STARTCHAR afii10042 +ENCODING 1064 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +A8 +A8 +A8 +A8 +A8 +A8 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10043 +ENCODING 1065 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +A8 +A8 +A8 +A8 +A8 +A8 +F8 +08 +08 +00 +ENDCHAR +STARTCHAR afii10044 +ENCODING 1066 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +C0 +40 +40 +70 +48 +48 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10045 +ENCODING 1067 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +E8 +98 +98 +E8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10046 +ENCODING 1068 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +80 +80 +80 +F0 +88 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10047 +ENCODING 1069 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +08 +78 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10048 +ENCODING 1070 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +90 +A8 +A8 +E8 +A8 +A8 +90 +00 +00 +00 +ENDCHAR +STARTCHAR afii10049 +ENCODING 1071 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +78 +88 +88 +78 +28 +48 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10065 +ENCODING 1072 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +08 +78 +88 +78 +00 +00 +00 +ENDCHAR +STARTCHAR afii10066 +ENCODING 1073 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +80 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10067 +ENCODING 1074 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F0 +88 +F0 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10068 +ENCODING 1075 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +40 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR afii10069 +ENCODING 1076 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +30 +50 +50 +50 +F8 +88 +00 +00 +ENDCHAR +STARTCHAR afii10070 +ENCODING 1077 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10072 +ENCODING 1078 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +A8 +A8 +70 +A8 +A8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10073 +ENCODING 1079 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +30 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10074 +ENCODING 1080 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +98 +A8 +C8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10075 +ENCODING 1081 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +88 +70 +00 +88 +98 +A8 +C8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10076 +ENCODING 1082 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +90 +E0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10077 +ENCODING 1083 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +38 +48 +48 +48 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10078 +ENCODING 1084 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +D8 +A8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10079 +ENCODING 1085 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +F8 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10080 +ENCODING 1086 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10081 +ENCODING 1087 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F8 +88 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10082 +ENCODING 1088 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F0 +88 +88 +88 +F0 +80 +80 +80 +ENDCHAR +STARTCHAR afii10083 +ENCODING 1089 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +80 +80 +80 +78 +00 +00 +00 +ENDCHAR +STARTCHAR afii10084 +ENCODING 1090 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F8 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR afii10085 +ENCODING 1091 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR afii10086 +ENCODING 1092 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +20 +70 +A8 +A8 +A8 +70 +20 +20 +00 +ENDCHAR +STARTCHAR afii10087 +ENCODING 1093 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +50 +20 +50 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10088 +ENCODING 1094 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +90 +90 +90 +90 +F8 +08 +00 +00 +ENDCHAR +STARTCHAR afii10089 +ENCODING 1095 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +78 +08 +08 +00 +00 +00 +ENDCHAR +STARTCHAR afii10090 +ENCODING 1096 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +A8 +A8 +A8 +A8 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10091 +ENCODING 1097 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +A8 +A8 +A8 +A8 +F8 +08 +08 +00 +ENDCHAR +STARTCHAR afii10092 +ENCODING 1098 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +C0 +40 +70 +48 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10093 +ENCODING 1099 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +E8 +98 +E8 +00 +00 +00 +ENDCHAR +STARTCHAR afii10094 +ENCODING 1100 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +80 +80 +F0 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10095 +ENCODING 1101 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +38 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10096 +ENCODING 1102 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +90 +A8 +E8 +A8 +90 +00 +00 +00 +ENDCHAR +STARTCHAR afii10097 +ENCODING 1103 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +88 +78 +48 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10071 +ENCODING 1105 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +00 +70 +88 +F8 +80 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10099 +ENCODING 1106 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +F0 +40 +78 +44 +44 +44 +44 +04 +18 +00 +ENDCHAR +STARTCHAR afii10100 +ENCODING 1107 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +78 +40 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR afii10101 +ENCODING 1108 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +E0 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10102 +ENCODING 1109 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +80 +70 +08 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10103 +ENCODING 1110 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10104 +ENCODING 1111 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +00 +60 +20 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10105 +ENCODING 1112 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +08 +00 +38 +08 +08 +08 +08 +08 +08 +70 +ENDCHAR +STARTCHAR afii10106 +ENCODING 1113 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +60 +A0 +B0 +A8 +B0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10107 +ENCODING 1114 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +A0 +A0 +F0 +A8 +B0 +00 +00 +00 +ENDCHAR +STARTCHAR afii10108 +ENCODING 1115 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +F0 +40 +78 +44 +44 +44 +44 +00 +00 +00 +ENDCHAR +STARTCHAR afii10109 +ENCODING 1116 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +88 +90 +E0 +90 +88 +00 +00 +00 +ENDCHAR +STARTCHAR afii10110 +ENCODING 1118 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +88 +70 +00 +88 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR afii10193 +ENCODING 1119 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +88 +88 +88 +88 +F8 +20 +20 +00 +ENDCHAR +STARTCHAR afii10146 +ENCODING 1122 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +E0 +40 +40 +70 +48 +48 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10194 +ENCODING 1123 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +40 +E0 +40 +70 +48 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni0470 +ENCODING 1136 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +A8 +A8 +A8 +70 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni0471 +ENCODING 1137 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +A8 +A8 +70 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR afii10147 +ENCODING 1138 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +88 +F8 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10195 +ENCODING 1139 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +F8 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii10148 +ENCODING 1140 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +80 +98 +90 +50 +50 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR afii10196 +ENCODING 1141 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +80 +98 +50 +60 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni0476 +ENCODING 1142 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +A0 +50 +80 +98 +90 +50 +50 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni0477 +ENCODING 1143 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +A0 +50 +80 +98 +50 +60 +20 +00 +00 +00 +ENDCHAR +STARTCHAR afii10050 +ENCODING 1168 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +08 +78 +40 +40 +40 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR afii10098 +ENCODING 1169 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +08 +78 +40 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR afii57664 +ENCODING 1488 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +88 +48 +70 +A0 +90 +C8 +00 +00 +00 +ENDCHAR +STARTCHAR afii57665 +ENCODING 1489 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F0 +10 +10 +10 +10 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR afii57666 +ENCODING 1490 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +70 +10 +10 +10 +28 +48 +00 +00 +00 +ENDCHAR +STARTCHAR afii57667 +ENCODING 1491 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F8 +10 +10 +10 +10 +10 +00 +00 +00 +ENDCHAR +STARTCHAR afii57668 +ENCODING 1492 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F8 +10 +90 +90 +90 +90 +00 +00 +00 +ENDCHAR +STARTCHAR afii57669 +ENCODING 1493 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +70 +10 +10 +10 +10 +10 +00 +00 +00 +ENDCHAR +STARTCHAR afii57670 +ENCODING 1494 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F8 +20 +10 +10 +10 +10 +00 +00 +00 +ENDCHAR +STARTCHAR afii57671 +ENCODING 1495 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F8 +48 +48 +48 +48 +48 +00 +00 +00 +ENDCHAR +STARTCHAR afii57672 +ENCODING 1496 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +98 +A8 +A8 +88 +88 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR afii57673 +ENCODING 1497 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +30 +10 +10 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR afii57674 +ENCODING 1498 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F8 +08 +08 +08 +08 +08 +08 +08 +00 +ENDCHAR +STARTCHAR afii57675 +ENCODING 1499 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F8 +08 +08 +08 +08 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR afii57676 +ENCODING 1500 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +80 +F8 +08 +08 +10 +20 +40 +00 +00 +00 +ENDCHAR +STARTCHAR afii57677 +ENCODING 1501 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F8 +48 +48 +48 +48 +78 +00 +00 +00 +ENDCHAR +STARTCHAR afii57678 +ENCODING 1502 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +98 +A8 +48 +88 +88 +B8 +00 +00 +00 +ENDCHAR +STARTCHAR afii57679 +ENCODING 1503 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +30 +10 +10 +10 +10 +10 +10 +10 +00 +ENDCHAR +STARTCHAR afii57680 +ENCODING 1504 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +18 +08 +08 +08 +08 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR afii57681 +ENCODING 1505 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F8 +48 +48 +48 +50 +60 +00 +00 +00 +ENDCHAR +STARTCHAR afii57682 +ENCODING 1506 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +D8 +48 +48 +48 +50 +E0 +00 +00 +00 +ENDCHAR +STARTCHAR afii57683 +ENCODING 1507 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F8 +48 +48 +08 +08 +08 +08 +08 +00 +ENDCHAR +STARTCHAR afii57684 +ENCODING 1508 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F8 +48 +48 +08 +08 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR afii57685 +ENCODING 1509 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +90 +48 +50 +60 +40 +40 +40 +40 +00 +ENDCHAR +STARTCHAR afii57686 +ENCODING 1510 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +90 +48 +28 +10 +08 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR afii57687 +ENCODING 1511 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F8 +08 +88 +88 +88 +B0 +80 +80 +00 +ENDCHAR +STARTCHAR afii57688 +ENCODING 1512 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F0 +08 +08 +08 +08 +08 +00 +00 +00 +ENDCHAR +STARTCHAR afii57689 +ENCODING 1513 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +A8 +A8 +A8 +E8 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR afii57690 +ENCODING 1514 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F8 +48 +48 +48 +48 +C8 +00 +00 +00 +ENDCHAR +STARTCHAR uni1E02 +ENCODING 7682 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +F0 +88 +F0 +88 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR uni1E03 +ENCODING 7683 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +80 +80 +F0 +88 +88 +88 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR uni1E08 +ENCODING 7688 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni1E09 +ENCODING 7689 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni1E0A +ENCODING 7690 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +E0 +90 +88 +88 +90 +E0 +00 +00 +00 +ENDCHAR +STARTCHAR uni1E0B +ENCODING 7691 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +08 +08 +78 +88 +88 +88 +78 +00 +00 +00 +ENDCHAR +STARTCHAR uni1E1E +ENCODING 7710 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +F8 +80 +F0 +80 +80 +80 +00 +00 +00 +ENDCHAR +STARTCHAR uni1E1F +ENCODING 7711 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +38 +40 +40 +F0 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR uni1E40 +ENCODING 7744 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +88 +D8 +A8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR uni1E41 +ENCODING 7745 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +00 +D0 +A8 +A8 +A8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR uni1E56 +ENCODING 7766 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +F0 +88 +88 +F0 +80 +80 +00 +00 +00 +ENDCHAR +STARTCHAR uni1E57 +ENCODING 7767 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +00 +F0 +88 +88 +88 +F0 +80 +80 +80 +ENDCHAR +STARTCHAR uni1E60 +ENCODING 7776 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +70 +80 +70 +08 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni1E61 +ENCODING 7777 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +00 +78 +80 +70 +08 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR uni1E6A +ENCODING 7786 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +F8 +20 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni1E6B +ENCODING 7787 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +20 +20 +F8 +20 +20 +18 +00 +00 +00 +ENDCHAR +STARTCHAR Wgrave +ENCODING 7808 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +00 +88 +88 +A8 +A8 +D8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR wgrave +ENCODING 7809 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +20 +00 +88 +A8 +A8 +A8 +50 +00 +00 +00 +ENDCHAR +STARTCHAR Wacute +ENCODING 7810 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +20 +00 +88 +88 +A8 +A8 +D8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR wacute +ENCODING 7811 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +00 +88 +A8 +A8 +A8 +50 +00 +00 +00 +ENDCHAR +STARTCHAR Wdieresis +ENCODING 7812 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +00 +88 +88 +A8 +A8 +D8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR wdieresis +ENCODING 7813 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +00 +88 +A8 +A8 +A8 +50 +00 +00 +00 +ENDCHAR +STARTCHAR uni1E86 +ENCODING 7814 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +00 +88 +88 +A8 +A8 +D8 +88 +00 +00 +00 +ENDCHAR +STARTCHAR uni1E87 +ENCODING 7815 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +00 +88 +A8 +A8 +A8 +50 +00 +00 +00 +ENDCHAR +STARTCHAR Ygrave +ENCODING 7922 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +20 +00 +88 +50 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR ygrave +ENCODING 7923 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +20 +00 +88 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR uni2000 +ENCODING 8192 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2001 +ENCODING 8193 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2002 +ENCODING 8194 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2003 +ENCODING 8195 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2004 +ENCODING 8196 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2005 +ENCODING 8197 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2006 +ENCODING 8198 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2007 +ENCODING 8199 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2008 +ENCODING 8200 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2009 +ENCODING 8201 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni200A +ENCODING 8202 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2010 +ENCODING 8208 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +70 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2011 +ENCODING 8209 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +70 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR figuredash +ENCODING 8210 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +78 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR endash +ENCODING 8211 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +78 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR emdash +ENCODING 8212 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +F8 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR afii00208 +ENCODING 8213 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +FC +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2016 +ENCODING 8214 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +50 +50 +50 +50 +50 +50 +00 +00 +00 +ENDCHAR +STARTCHAR underscoredbl +ENCODING 8215 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +F8 +00 +F8 +ENDCHAR +STARTCHAR quoteleft +ENCODING 8216 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +20 +30 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR quoteright +ENCODING 8217 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +10 +20 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR quotesinglbase +ENCODING 8218 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +30 +10 +20 +00 +ENDCHAR +STARTCHAR quotereversed +ENCODING 8219 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +20 +10 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR quotedblleft +ENCODING 8220 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +48 +90 +D8 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR quotedblright +ENCODING 8221 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +D8 +48 +90 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR quotedblbase +ENCODING 8222 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +D8 +48 +90 +00 +ENDCHAR +STARTCHAR uni201F +ENCODING 8223 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +D8 +90 +48 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR dagger +ENCODING 8224 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +20 +70 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR daggerdbl +ENCODING 8225 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +20 +70 +20 +70 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR bullet +ENCODING 8226 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +30 +78 +78 +78 +30 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2023 +ENCODING 8227 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +40 +60 +70 +78 +70 +60 +40 +00 +00 +00 +ENDCHAR +STARTCHAR onedotenleader +ENCODING 8228 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +20 +00 +00 +00 +ENDCHAR +STARTCHAR twodotenleader +ENCODING 8229 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +50 +00 +00 +00 +ENDCHAR +STARTCHAR ellipsis +ENCODING 8230 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +A8 +00 +00 +00 +ENDCHAR +STARTCHAR perthousand +ENCODING 8240 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +C0 +D0 +20 +58 +98 +60 +60 +00 +00 +00 +ENDCHAR +STARTCHAR minute +ENCODING 8242 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +10 +20 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR second +ENCODING 8243 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +48 +48 +90 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2034 +ENCODING 8244 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +54 +54 +A8 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2035 +ENCODING 8245 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +10 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2036 +ENCODING 8246 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +90 +90 +48 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2037 +ENCODING 8247 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +A8 +A8 +54 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR guilsinglleft +ENCODING 8249 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +10 +20 +40 +20 +10 +00 +00 +00 +ENDCHAR +STARTCHAR guilsinglright +ENCODING 8250 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +40 +20 +10 +20 +40 +00 +00 +00 +ENDCHAR +STARTCHAR exclamdbl +ENCODING 8252 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +50 +50 +50 +50 +50 +50 +00 +50 +00 +00 +00 +ENDCHAR +STARTCHAR uni203E +ENCODING 8254 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +F8 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR fraction +ENCODING 8260 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +08 +08 +10 +10 +20 +20 +40 +40 +80 +80 +00 +00 +ENDCHAR +STARTCHAR zerosuperior +ENCODING 8304 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +50 +50 +20 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2071 +ENCODING 8305 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +00 +60 +20 +70 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR foursuperior +ENCODING 8308 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +40 +60 +70 +20 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR fivesuperior +ENCODING 8309 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +70 +40 +60 +10 +60 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR sixsuperior +ENCODING 8310 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +40 +60 +50 +20 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR sevensuperior +ENCODING 8311 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +70 +10 +20 +20 +20 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR eightsuperior +ENCODING 8312 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +20 +50 +20 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR ninesuperior +ENCODING 8313 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +30 +10 +60 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni207A +ENCODING 8314 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +70 +20 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni207B +ENCODING 8315 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni207C +ENCODING 8316 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +00 +70 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR parenleftsuperior +ENCODING 8317 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +40 +40 +40 +20 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR parenrightsuperior +ENCODING 8318 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +10 +10 +10 +20 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR nsuperior +ENCODING 8319 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +60 +50 +50 +50 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR zeroinferior +ENCODING 8320 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +20 +50 +50 +50 +20 +00 +ENDCHAR +STARTCHAR oneinferior +ENCODING 8321 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +20 +60 +20 +20 +20 +00 +ENDCHAR +STARTCHAR twoinferior +ENCODING 8322 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +20 +50 +10 +20 +70 +00 +ENDCHAR +STARTCHAR threeinferior +ENCODING 8323 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +20 +50 +20 +10 +60 +00 +ENDCHAR +STARTCHAR fourinferior +ENCODING 8324 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +40 +40 +60 +70 +20 +00 +ENDCHAR +STARTCHAR fiveinferior +ENCODING 8325 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +70 +40 +60 +10 +60 +00 +ENDCHAR +STARTCHAR sixinferior +ENCODING 8326 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +30 +40 +60 +50 +20 +00 +ENDCHAR +STARTCHAR seveninferior +ENCODING 8327 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +70 +10 +20 +20 +20 +00 +ENDCHAR +STARTCHAR eightinferior +ENCODING 8328 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +20 +50 +20 +50 +20 +00 +ENDCHAR +STARTCHAR nineinferior +ENCODING 8329 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +20 +50 +30 +10 +60 +00 +ENDCHAR +STARTCHAR uni208A +ENCODING 8330 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +20 +70 +20 +00 +00 +ENDCHAR +STARTCHAR uni208B +ENCODING 8331 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +70 +00 +00 +00 +ENDCHAR +STARTCHAR uni208C +ENCODING 8332 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +70 +00 +70 +00 +00 +ENDCHAR +STARTCHAR parenleftinferior +ENCODING 8333 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +20 +40 +40 +40 +20 +00 +ENDCHAR +STARTCHAR parenrightinferior +ENCODING 8334 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +20 +10 +10 +10 +20 +00 +ENDCHAR +STARTCHAR franc +ENCODING 8355 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +80 +D8 +A0 +A0 +A0 +A0 +00 +00 +00 +ENDCHAR +STARTCHAR lira +ENCODING 8356 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +48 +E0 +40 +E0 +40 +48 +B0 +00 +00 +00 +ENDCHAR +STARTCHAR peseta +ENCODING 8359 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +48 +FC +48 +70 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR Euro +ENCODING 8364 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +30 +48 +E0 +40 +E0 +48 +30 +00 +00 +00 +ENDCHAR +STARTCHAR uni20AF +ENCODING 8367 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +E0 +50 +48 +48 +48 +E8 +D0 +00 +00 +00 +ENDCHAR +STARTCHAR uni20D0 +ENCODING 8400 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +F8 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni20D1 +ENCODING 8401 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +F8 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni20D2 +ENCODING 8402 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +20 +20 +20 +20 +20 +20 +20 +00 +00 +ENDCHAR +STARTCHAR uni20D3 +ENCODING 8403 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +20 +20 +20 +20 +20 +20 +20 +00 +00 +ENDCHAR +STARTCHAR uni20D4 +ENCODING 8404 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +B0 +C8 +E0 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni20D5 +ENCODING 8405 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +68 +98 +38 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni20D6 +ENCODING 8406 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +F8 +40 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni20D7 +ENCODING 8407 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +F8 +10 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2102 +ENCODING 8450 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +A8 +A0 +A0 +A0 +A8 +70 +00 +00 +00 +ENDCHAR +STARTCHAR afii61248 +ENCODING 8453 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +60 +80 +80 +60 +00 +30 +48 +48 +30 +00 +00 +00 +ENDCHAR +STARTCHAR afii61289 +ENCODING 8467 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +28 +28 +28 +30 +30 +20 +58 +00 +00 +00 +ENDCHAR +STARTCHAR uni2115 +ENCODING 8469 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +C8 +C8 +E8 +D8 +D8 +C8 +00 +00 +00 +ENDCHAR +STARTCHAR afii61352 +ENCODING 8470 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +A0 +A0 +E0 +E8 +F4 +B4 +A8 +00 +00 +00 +ENDCHAR +STARTCHAR uni211A +ENCODING 8474 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +A8 +A8 +A8 +A8 +A8 +70 +18 +00 +00 +ENDCHAR +STARTCHAR uni211D +ENCODING 8477 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F0 +A8 +A8 +B0 +B0 +A8 +A8 +00 +00 +00 +ENDCHAR +STARTCHAR trademark +ENCODING 8482 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F4 +5C +54 +54 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2124 +ENCODING 8484 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +28 +50 +50 +A0 +A0 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR Omega +ENCODING 8486 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +88 +88 +50 +50 +D8 +00 +00 +00 +ENDCHAR +STARTCHAR uni2127 +ENCODING 8487 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +D8 +50 +50 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR estimated +ENCODING 8494 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +D8 +F8 +C0 +70 +00 +00 +00 +ENDCHAR +STARTCHAR oneeighth +ENCODING 8539 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +80 +80 +90 +A8 +10 +28 +10 +00 +00 +00 +ENDCHAR +STARTCHAR threeeighths +ENCODING 8540 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +40 +A0 +40 +28 +D4 +08 +14 +08 +00 +00 +00 +ENDCHAR +STARTCHAR fiveeighths +ENCODING 8541 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +E0 +80 +C0 +28 +D4 +08 +14 +08 +00 +00 +00 +ENDCHAR +STARTCHAR seveneighths +ENCODING 8542 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +E0 +20 +40 +48 +54 +08 +14 +08 +00 +00 +00 +ENDCHAR +STARTCHAR arrowleft +ENCODING 8592 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +20 +40 +F8 +40 +20 +00 +00 +00 +00 +ENDCHAR +STARTCHAR arrowup +ENCODING 8593 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +70 +A8 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR arrowright +ENCODING 8594 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +20 +10 +F8 +10 +20 +00 +00 +00 +00 +ENDCHAR +STARTCHAR arrowdown +ENCODING 8595 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +20 +20 +20 +A8 +70 +20 +00 +00 +00 +ENDCHAR +STARTCHAR arrowboth +ENCODING 8596 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +48 +FC +48 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR arrowupdn +ENCODING 8597 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +70 +A8 +20 +20 +20 +A8 +70 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni21A4 +ENCODING 8612 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +24 +44 +FC +44 +24 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni21A5 +ENCODING 8613 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +70 +A8 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni21A6 +ENCODING 8614 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +90 +88 +FC +88 +90 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni21A7 +ENCODING 8615 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +20 +20 +20 +A8 +70 +20 +00 +00 +00 +ENDCHAR +STARTCHAR arrowupdnbse +ENCODING 8616 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +70 +A8 +20 +A8 +70 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni21C4 +ENCODING 8644 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +10 +F8 +10 +20 +40 +F8 +40 +20 +00 +ENDCHAR +STARTCHAR uni21C6 +ENCODING 8646 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +40 +F8 +40 +20 +10 +F8 +10 +20 +00 +ENDCHAR +STARTCHAR uni21CB +ENCODING 8651 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +20 +40 +F8 +00 +F8 +10 +20 +00 +ENDCHAR +STARTCHAR uni21CC +ENCODING 8652 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +20 +10 +F8 +00 +F8 +40 +20 +00 +ENDCHAR +STARTCHAR arrowdblleft +ENCODING 8656 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +10 +20 +7C +C0 +7C +20 +10 +00 +00 +00 +ENDCHAR +STARTCHAR arrowdblup +ENCODING 8657 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +50 +D8 +50 +50 +50 +50 +00 +00 +00 +ENDCHAR +STARTCHAR arrowdblright +ENCODING 8658 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +10 +F8 +0C +F8 +10 +20 +00 +00 +00 +ENDCHAR +STARTCHAR arrowdbldown +ENCODING 8659 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +50 +50 +50 +D8 +50 +20 +00 +00 +00 +ENDCHAR +STARTCHAR arrowdblboth +ENCODING 8660 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +48 +FC +84 +FC +48 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni21D5 +ENCODING 8661 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +D8 +50 +50 +50 +50 +D8 +50 +20 +00 +ENDCHAR +STARTCHAR universal +ENCODING 8704 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +F8 +88 +50 +50 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni2201 +ENCODING 8705 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +50 +40 +40 +40 +50 +20 +00 +00 +00 +ENDCHAR +STARTCHAR partialdiff +ENCODING 8706 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +30 +48 +08 +38 +48 +48 +30 +00 +00 +00 +ENDCHAR +STARTCHAR existential +ENCODING 8707 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +08 +08 +78 +08 +08 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni2204 +ENCODING 8708 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +10 +F8 +28 +28 +78 +28 +28 +F8 +40 +40 +00 +ENDCHAR +STARTCHAR emptyset +ENCODING 8709 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +34 +48 +94 +A4 +48 +B0 +00 +00 +00 +ENDCHAR +STARTCHAR Delta +ENCODING 8710 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +50 +50 +50 +88 +88 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR gradient +ENCODING 8711 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F8 +88 +88 +50 +50 +50 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR element +ENCODING 8712 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +78 +80 +F0 +80 +78 +00 +00 +00 +00 +ENDCHAR +STARTCHAR notelement +ENCODING 8713 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +10 +78 +A0 +F0 +A0 +78 +40 +40 +00 +00 +ENDCHAR +STARTCHAR suchthat +ENCODING 8715 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F0 +08 +78 +08 +F0 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni220C +ENCODING 8716 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +10 +10 +F0 +28 +78 +28 +F0 +40 +40 +00 +00 +ENDCHAR +STARTCHAR product +ENCODING 8719 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +F8 +50 +50 +50 +50 +50 +50 +50 +50 +50 +00 +00 +ENDCHAR +STARTCHAR uni2210 +ENCODING 8720 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +50 +50 +50 +50 +50 +50 +50 +50 +F8 +00 +00 +ENDCHAR +STARTCHAR summation +ENCODING 8721 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +F8 +80 +40 +20 +10 +10 +20 +40 +80 +F8 +00 +00 +ENDCHAR +STARTCHAR minus +ENCODING 8722 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +F8 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2213 +ENCODING 8723 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +00 +20 +20 +F8 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR fraction +ENCODING 8725 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +08 +08 +10 +10 +20 +20 +40 +40 +80 +80 +00 +00 +ENDCHAR +STARTCHAR uni2218 +ENCODING 8728 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +30 +48 +48 +30 +00 +00 +00 +00 +ENDCHAR +STARTCHAR periodcentered +ENCODING 8729 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +30 +78 +78 +30 +00 +00 +00 +00 +ENDCHAR +STARTCHAR radical +ENCODING 8730 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +04 +04 +08 +08 +90 +50 +20 +00 +00 +00 +ENDCHAR +STARTCHAR proportional +ENCODING 8733 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +28 +50 +28 +00 +00 +00 +00 +ENDCHAR +STARTCHAR infinity +ENCODING 8734 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +50 +A8 +50 +00 +00 +00 +00 +ENDCHAR +STARTCHAR orthogonal +ENCODING 8735 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +80 +80 +80 +80 +F8 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2221 +ENCODING 8737 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +10 +10 +F0 +28 +48 +7C +08 +08 +00 +ENDCHAR +STARTCHAR uni2223 +ENCODING 8739 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +20 +20 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni2224 +ENCODING 8740 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +28 +30 +20 +60 +A0 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni2225 +ENCODING 8741 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +50 +50 +50 +50 +50 +50 +00 +00 +00 +ENDCHAR +STARTCHAR uni2226 +ENCODING 8742 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +50 +58 +70 +D0 +50 +50 +00 +00 +00 +ENDCHAR +STARTCHAR logicaland +ENCODING 8743 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +20 +20 +50 +50 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR logicalor +ENCODING 8744 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +88 +88 +50 +50 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR intersection +ENCODING 8745 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +70 +88 +88 +88 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR union +ENCODING 8746 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR integral +ENCODING 8747 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +28 +20 +20 +20 +20 +20 +20 +A0 +40 +00 +00 +ENDCHAR +STARTCHAR uni222E +ENCODING 8750 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +28 +20 +70 +A8 +A8 +70 +20 +A0 +40 +00 +00 +ENDCHAR +STARTCHAR similar +ENCODING 8764 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +40 +A8 +10 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2243 +ENCODING 8771 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +40 +A8 +10 +00 +F8 +00 +00 +00 +00 +ENDCHAR +STARTCHAR congruent +ENCODING 8773 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +40 +A8 +10 +00 +F8 +00 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR approxequal +ENCODING 8776 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +40 +A8 +50 +A8 +10 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2249 +ENCODING 8777 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +60 +A8 +70 +A8 +30 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni2259 +ENCODING 8793 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +50 +00 +F8 +00 +F8 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni225F +ENCODING 8799 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +50 +10 +20 +00 +20 +F8 +00 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR notequal +ENCODING 8800 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +10 +10 +F8 +20 +F8 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR equivalence +ENCODING 8801 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F8 +00 +F8 +00 +F8 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2262 +ENCODING 8802 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +F8 +20 +F8 +20 +F8 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni2263 +ENCODING 8803 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +00 +F8 +00 +F8 +00 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR lessequal +ENCODING 8804 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +18 +60 +80 +60 +18 +00 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR greaterequal +ENCODING 8805 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +C0 +30 +08 +30 +C0 +00 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni226A +ENCODING 8810 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +24 +48 +90 +48 +24 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni226B +ENCODING 8811 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +90 +48 +24 +48 +90 +00 +00 +00 +00 +ENDCHAR +STARTCHAR propersubset +ENCODING 8834 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +78 +80 +80 +80 +80 +78 +00 +00 +00 +ENDCHAR +STARTCHAR propersuperset +ENCODING 8835 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F0 +08 +08 +08 +08 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR notsubset +ENCODING 8836 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +78 +A0 +A0 +A0 +A0 +78 +20 +00 +00 +ENDCHAR +STARTCHAR uni2285 +ENCODING 8837 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +F0 +28 +28 +28 +28 +F0 +20 +00 +00 +ENDCHAR +STARTCHAR reflexsubset +ENCODING 8838 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +78 +80 +80 +80 +80 +78 +00 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR reflexsuperset +ENCODING 8839 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F0 +08 +08 +08 +08 +F0 +00 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni2288 +ENCODING 8840 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +78 +A0 +A0 +A0 +A0 +78 +20 +F8 +20 +00 +00 +ENDCHAR +STARTCHAR uni2289 +ENCODING 8841 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +F0 +28 +28 +28 +28 +F0 +20 +F8 +20 +00 +00 +ENDCHAR +STARTCHAR uni228A +ENCODING 8842 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +78 +80 +80 +80 +80 +78 +20 +F8 +20 +00 +00 +ENDCHAR +STARTCHAR uni228B +ENCODING 8843 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F0 +08 +08 +08 +08 +F0 +20 +F8 +20 +00 +00 +ENDCHAR +STARTCHAR circleplus +ENCODING 8853 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +70 +A8 +F8 +A8 +70 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2296 +ENCODING 8854 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +70 +88 +F8 +88 +70 +00 +00 +00 +00 +ENDCHAR +STARTCHAR circlemultiply +ENCODING 8855 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +70 +D8 +A8 +D8 +70 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2298 +ENCODING 8856 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +70 +98 +A8 +C8 +70 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2299 +ENCODING 8857 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +70 +88 +A8 +88 +70 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni229E +ENCODING 8862 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F8 +A8 +F8 +A8 +F8 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni229F +ENCODING 8863 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F8 +88 +F8 +88 +F8 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni22A0 +ENCODING 8864 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F8 +D8 +A8 +D8 +F8 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni22A1 +ENCODING 8865 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +F8 +88 +A8 +88 +F8 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni22A2 +ENCODING 8866 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +80 +80 +80 +F8 +80 +80 +80 +00 +00 +00 +ENDCHAR +STARTCHAR uni22A3 +ENCODING 8867 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +08 +08 +08 +F8 +08 +08 +08 +00 +00 +00 +ENDCHAR +STARTCHAR uni22A4 +ENCODING 8868 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +F8 +20 +20 +20 +20 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR perpendicular +ENCODING 8869 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +20 +20 +20 +20 +20 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni22A6 +ENCODING 8870 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +40 +40 +40 +70 +40 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR uni22A7 +ENCODING 8871 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +40 +40 +70 +40 +70 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR uni22A8 +ENCODING 8872 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +80 +80 +F8 +80 +F8 +80 +80 +00 +00 +00 +ENDCHAR +STARTCHAR uni22A9 +ENCODING 8873 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +A0 +A0 +A0 +B8 +A0 +A0 +A0 +00 +00 +00 +ENDCHAR +STARTCHAR uni22C0 +ENCODING 8896 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +50 +50 +50 +50 +88 +88 +88 +00 +00 +ENDCHAR +STARTCHAR uni22C1 +ENCODING 8897 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +88 +88 +88 +50 +50 +50 +50 +20 +20 +20 +00 +00 +ENDCHAR +STARTCHAR uni22C2 +ENCODING 8898 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +70 +88 +88 +88 +88 +88 +88 +88 +88 +88 +00 +00 +ENDCHAR +STARTCHAR uni22C3 +ENCODING 8899 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +88 +88 +88 +88 +88 +88 +88 +88 +88 +70 +00 +00 +ENDCHAR +STARTCHAR dotmath +ENCODING 8901 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +20 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni22EE +ENCODING 8942 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +00 +00 +20 +00 +00 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni22EF +ENCODING 8943 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +A8 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni22F0 +ENCODING 8944 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +08 +00 +00 +20 +00 +00 +80 +00 +00 +00 +ENDCHAR +STARTCHAR uni22F1 +ENCODING 8945 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +80 +00 +00 +20 +00 +00 +08 +00 +00 +00 +ENDCHAR +STARTCHAR uni2300 +ENCODING 8960 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +98 +A8 +C8 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR house +ENCODING 8962 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +20 +50 +88 +88 +88 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni2308 +ENCODING 8968 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +38 +20 +20 +20 +20 +20 +20 +20 +20 +20 +20 +00 +ENDCHAR +STARTCHAR uni2309 +ENCODING 8969 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +70 +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +00 +ENDCHAR +STARTCHAR uni230A +ENCODING 8970 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +20 +20 +20 +20 +38 +00 +ENDCHAR +STARTCHAR uni230B +ENCODING 8971 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +70 +00 +ENDCHAR +STARTCHAR revlogicalnot +ENCODING 8976 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +78 +40 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR integraltp +ENCODING 8992 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +08 +14 +10 +10 +10 +10 +10 +10 +10 +10 +10 +ENDCHAR +STARTCHAR integralbt +ENCODING 8993 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +10 +10 +10 +10 +10 +10 +10 +10 +50 +20 +00 +ENDCHAR +STARTCHAR uni23BA +ENCODING 9146 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +FC +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni23BB +ENCODING 9147 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +FC +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni23BC +ENCODING 9148 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +FC +00 +00 +00 +ENDCHAR +STARTCHAR uni23BD +ENCODING 9149 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +FC +ENDCHAR +STARTCHAR uni2409 +ENCODING 9225 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +A0 +A0 +E0 +A0 +BC +08 +08 +08 +08 +00 +00 +ENDCHAR +STARTCHAR uni240A +ENCODING 9226 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +80 +80 +80 +9C +F0 +18 +10 +10 +00 +00 +00 +ENDCHAR +STARTCHAR uni240B +ENCODING 9227 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +A0 +A0 +A0 +5C +48 +08 +08 +08 +00 +00 +00 +ENDCHAR +STARTCHAR uni240C +ENCODING 9228 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +E0 +80 +C0 +9C +90 +1C +10 +10 +00 +00 +00 +ENDCHAR +STARTCHAR uni240D +ENCODING 9229 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +60 +80 +80 +98 +74 +18 +14 +14 +00 +00 +00 +ENDCHAR +STARTCHAR uni2420 +ENCODING 9248 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +60 +80 +40 +38 +D4 +18 +10 +10 +00 +00 +00 +ENDCHAR +STARTCHAR uni2423 +ENCODING 9251 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +88 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni2424 +ENCODING 9252 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +A0 +E0 +E0 +E0 +B0 +10 +10 +10 +1C +00 +00 +00 +ENDCHAR +STARTCHAR uni2440 +ENCODING 9280 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +38 +28 +28 +20 +A0 +A0 +E0 +00 +00 +00 +ENDCHAR +STARTCHAR uni2441 +ENCODING 9281 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +08 +08 +08 +F8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR uni2442 +ENCODING 9282 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +88 +88 +88 +F8 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni2443 +ENCODING 9283 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +20 +20 +F8 +88 +88 +88 +00 +00 +00 +ENDCHAR +STARTCHAR uni2444 +ENCODING 9284 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +F8 +A8 +20 +20 +20 +A8 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni2445 +ENCODING 9285 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +88 +D8 +A8 +D8 +88 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF100000 +ENCODING 9472 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +FC +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2501 +ENCODING 9473 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +FC +FC +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF110000 +ENCODING 9474 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +20 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2503 +ENCODING 9475 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni2504 +ENCODING 9476 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +B4 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2505 +ENCODING 9477 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +B4 +B4 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2506 +ENCODING 9478 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +00 +20 +20 +20 +20 +00 +20 +20 +20 +ENDCHAR +STARTCHAR uni2507 +ENCODING 9479 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +00 +30 +30 +30 +30 +00 +30 +30 +30 +ENDCHAR +STARTCHAR uni2508 +ENCODING 9480 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +B4 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2509 +ENCODING 9481 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +B4 +B4 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni250A +ENCODING 9482 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +00 +20 +20 +00 +20 +20 +00 +20 +20 +ENDCHAR +STARTCHAR uni250B +ENCODING 9483 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +00 +30 +30 +00 +30 +30 +00 +30 +30 +ENDCHAR +STARTCHAR SF010000 +ENCODING 9484 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +3F +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni250D +ENCODING 9485 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +3F +3F +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni250E +ENCODING 9486 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +3F +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni250F +ENCODING 9487 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +3F +3F +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR SF030000 +ENCODING 9488 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +E0 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2511 +ENCODING 9489 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +E0 +E0 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2512 +ENCODING 9490 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +F0 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni2513 +ENCODING 9491 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +F0 +F0 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR SF020000 +ENCODING 9492 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +3F +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2515 +ENCODING 9493 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +3F +3F +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2516 +ENCODING 9494 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +30 +3F +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2517 +ENCODING 9495 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +3F +3F +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF040000 +ENCODING 9496 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +E0 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2519 +ENCODING 9497 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +E0 +E0 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni251A +ENCODING 9498 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +30 +F0 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni251B +ENCODING 9499 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +F0 +F0 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF080000 +ENCODING 9500 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +3F +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni251D +ENCODING 9501 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +3F +3F +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni251E +ENCODING 9502 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +30 +3F +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni251F +ENCODING 9503 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +3F +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni2520 +ENCODING 9504 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +30 +3F +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni2521 +ENCODING 9505 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +3F +3F +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2522 +ENCODING 9506 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +3F +3F +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni2523 +ENCODING 9507 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +3F +3F +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR SF090000 +ENCODING 9508 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +E0 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2525 +ENCODING 9509 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +E0 +E0 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2526 +ENCODING 9510 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +30 +E0 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2527 +ENCODING 9511 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +F0 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni2528 +ENCODING 9512 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +30 +F0 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni2529 +ENCODING 9513 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +F0 +E0 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni252A +ENCODING 9514 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +E0 +F0 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni252B +ENCODING 9515 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +F0 +F0 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR SF060000 +ENCODING 9516 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +FF +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni252D +ENCODING 9517 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +E0 +FF +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni252E +ENCODING 9518 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +3F +FF +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni252F +ENCODING 9519 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +FF +FF +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2530 +ENCODING 9520 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +FF +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni2531 +ENCODING 9521 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +E0 +FF +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni2532 +ENCODING 9522 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +3F +FF +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni2533 +ENCODING 9523 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +FF +FF +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR SF070000 +ENCODING 9524 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +FF +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2535 +ENCODING 9525 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +E0 +FF +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2536 +ENCODING 9526 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +3F +FF +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2537 +ENCODING 9527 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +FF +FF +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2538 +ENCODING 9528 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +30 +FF +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2539 +ENCODING 9529 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +F0 +FF +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni253A +ENCODING 9530 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +3F +FF +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni253B +ENCODING 9531 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +FF +FF +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF050000 +ENCODING 9532 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +FF +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni253D +ENCODING 9533 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +E0 +FF +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni253E +ENCODING 9534 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +3F +FF +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni253F +ENCODING 9535 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +FF +FF +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2540 +ENCODING 9536 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +30 +FF +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2541 +ENCODING 9537 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +FF +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni2542 +ENCODING 9538 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +30 +FF +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni2543 +ENCODING 9539 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +F0 +FF +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2544 +ENCODING 9540 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +3F +FF +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2545 +ENCODING 9541 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +E0 +FF +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni2546 +ENCODING 9542 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +3F +FF +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni2547 +ENCODING 9543 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +FF +FF +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2548 +ENCODING 9544 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +FF +FF +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2549 +ENCODING 9545 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +F0 +FF +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni254A +ENCODING 9546 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +3F +FF +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni254B +ENCODING 9547 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +FF +FF +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni254C +ENCODING 9548 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +EC +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni254D +ENCODING 9549 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +EC +EC +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni254E +ENCODING 9550 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +00 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni254F +ENCODING 9551 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +30 +00 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR SF430000 +ENCODING 9552 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +FC +00 +FC +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF240000 +ENCODING 9553 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +50 +50 +50 +50 +50 +50 +50 +50 +50 +50 +50 +ENDCHAR +STARTCHAR SF510000 +ENCODING 9554 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +3F +20 +3F +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF520000 +ENCODING 9555 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +7F +50 +50 +50 +50 +50 +ENDCHAR +STARTCHAR SF390000 +ENCODING 9556 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +7C +40 +5C +50 +50 +50 +50 +ENDCHAR +STARTCHAR SF220000 +ENCODING 9557 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +E0 +20 +E0 +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF210000 +ENCODING 9558 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +F0 +50 +50 +50 +50 +50 +ENDCHAR +STARTCHAR SF250000 +ENCODING 9559 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +F0 +10 +D0 +50 +50 +50 +50 +ENDCHAR +STARTCHAR SF500000 +ENCODING 9560 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +3C +20 +3C +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF490000 +ENCODING 9561 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +50 +50 +50 +50 +50 +7C +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF380000 +ENCODING 9562 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +50 +50 +50 +50 +5C +40 +7C +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF280000 +ENCODING 9563 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +E0 +20 +E0 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF270000 +ENCODING 9564 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +50 +50 +50 +50 +50 +F0 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF260000 +ENCODING 9565 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +50 +50 +50 +50 +D0 +10 +F0 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF360000 +ENCODING 9566 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +3C +20 +3C +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF370000 +ENCODING 9567 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +50 +50 +50 +50 +50 +5C +50 +50 +50 +50 +50 +ENDCHAR +STARTCHAR SF420000 +ENCODING 9568 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +50 +50 +50 +50 +5C +40 +5C +50 +50 +50 +50 +ENDCHAR +STARTCHAR SF190000 +ENCODING 9569 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +E0 +20 +E0 +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF200000 +ENCODING 9570 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +50 +50 +50 +50 +50 +D0 +50 +50 +50 +50 +50 +ENDCHAR +STARTCHAR SF230000 +ENCODING 9571 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +50 +50 +50 +50 +D0 +10 +D0 +50 +50 +50 +50 +ENDCHAR +STARTCHAR SF470000 +ENCODING 9572 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +FC +00 +FC +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF480000 +ENCODING 9573 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +FC +50 +50 +50 +50 +50 +ENDCHAR +STARTCHAR SF410000 +ENCODING 9574 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +FC +00 +DC +50 +50 +50 +50 +ENDCHAR +STARTCHAR SF450000 +ENCODING 9575 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +FC +00 +FC +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF460000 +ENCODING 9576 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +50 +50 +50 +50 +50 +FC +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF400000 +ENCODING 9577 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +50 +50 +50 +50 +DC +00 +FC +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF540000 +ENCODING 9578 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +FC +20 +FC +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF530000 +ENCODING 9579 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +50 +50 +50 +50 +50 +FC +50 +50 +50 +50 +50 +ENDCHAR +STARTCHAR SF440000 +ENCODING 9580 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +50 +50 +50 +50 +50 +DC +00 +DC +50 +50 +50 +50 +ENDCHAR +STARTCHAR uni256D +ENCODING 9581 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +0C +10 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni256E +ENCODING 9582 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +80 +40 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni256F +ENCODING 9583 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +40 +80 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2570 +ENCODING 9584 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +10 +0C +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2571 +ENCODING 9585 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +04 +04 +08 +08 +10 +10 +20 +20 +40 +40 +80 +80 +ENDCHAR +STARTCHAR uni2572 +ENCODING 9586 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +80 +80 +40 +40 +20 +20 +10 +10 +08 +08 +04 +04 +ENDCHAR +STARTCHAR uni2573 +ENCODING 9587 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +84 +84 +48 +48 +30 +30 +30 +30 +48 +48 +84 +84 +ENDCHAR +STARTCHAR uni2574 +ENCODING 9588 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +E0 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2575 +ENCODING 9589 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2576 +ENCODING 9590 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +3F +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2577 +ENCODING 9591 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +20 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2578 +ENCODING 9592 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +E0 +E0 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2579 +ENCODING 9593 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +30 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni257A +ENCODING 9594 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +3F +3F +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni257B +ENCODING 9595 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni257C +ENCODING 9596 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +3F +FF +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni257D +ENCODING 9597 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +20 +20 +20 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni257E +ENCODING 9598 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +E0 +FF +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni257F +ENCODING 9599 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +30 +30 +30 +20 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR upblock +ENCODING 9600 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +FC +FC +FC +FC +FC +FC +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2581 +ENCODING 9601 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +FC +ENDCHAR +STARTCHAR uni2582 +ENCODING 9602 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +FC +FC +FC +ENDCHAR +STARTCHAR uni2583 +ENCODING 9603 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +00 +FC +FC +FC +FC +FC +ENDCHAR +STARTCHAR dnblock +ENCODING 9604 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +FC +FC +FC +FC +FC +FC +ENDCHAR +STARTCHAR uni2585 +ENCODING 9605 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +FC +FC +FC +FC +FC +FC +FC +ENDCHAR +STARTCHAR uni2586 +ENCODING 9606 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +FC +FC +FC +FC +FC +FC +FC +FC +FC +ENDCHAR +STARTCHAR uni2587 +ENCODING 9607 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +FC +FC +FC +FC +FC +FC +FC +FC +FC +FC +FC +ENDCHAR +STARTCHAR block +ENCODING 9608 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +FC +FC +FC +FC +FC +FC +FC +FC +FC +FC +FC +FC +ENDCHAR +STARTCHAR uni2589 +ENCODING 9609 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +F8 +F8 +F8 +F8 +F8 +F8 +F8 +F8 +F8 +F8 +F8 +F8 +ENDCHAR +STARTCHAR uni258A +ENCODING 9610 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +F0 +F0 +F0 +F0 +F0 +F0 +F0 +F0 +F0 +F0 +F0 +F0 +ENDCHAR +STARTCHAR uni258B +ENCODING 9611 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +F0 +F0 +F0 +F0 +F0 +F0 +F0 +F0 +F0 +F0 +F0 +F0 +ENDCHAR +STARTCHAR lfblock +ENCODING 9612 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +E0 +ENDCHAR +STARTCHAR uni258D +ENCODING 9613 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni258E +ENCODING 9614 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni258F +ENCODING 9615 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR rtblock +ENCODING 9616 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +1C +1C +1C +1C +1C +1C +1C +1C +1C +1C +1C +1C +ENDCHAR +STARTCHAR ltshade +ENCODING 9617 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +A8 +00 +54 +00 +A8 +00 +54 +00 +A8 +00 +54 +00 +ENDCHAR +STARTCHAR shade +ENCODING 9618 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +A8 +54 +A8 +54 +A8 +54 +A8 +54 +A8 +54 +A8 +54 +ENDCHAR +STARTCHAR dkshade +ENCODING 9619 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +A8 +FC +54 +FC +A8 +FC +54 +FC +A8 +FC +54 +FC +ENDCHAR +STARTCHAR uni2594 +ENCODING 9620 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +FC +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2595 +ENCODING 9621 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +04 +04 +04 +04 +04 +04 +04 +04 +04 +04 +04 +04 +ENDCHAR +STARTCHAR uni2596 +ENCODING 9622 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +E0 +E0 +E0 +E0 +E0 +E0 +ENDCHAR +STARTCHAR uni2597 +ENCODING 9623 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +00 +1C +1C +1C +1C +1C +1C +ENDCHAR +STARTCHAR uni2598 +ENCODING 9624 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +E0 +E0 +E0 +E0 +E0 +E0 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2599 +ENCODING 9625 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +E0 +E0 +E0 +E0 +E0 +E0 +FC +FC +FC +FC +FC +FC +ENDCHAR +STARTCHAR uni259A +ENCODING 9626 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +E0 +E0 +E0 +E0 +E0 +E0 +1C +1C +1C +1C +1C +1C +ENDCHAR +STARTCHAR uni259B +ENCODING 9627 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +FC +FC +FC +FC +FC +FC +E0 +E0 +E0 +E0 +E0 +E0 +ENDCHAR +STARTCHAR uni259C +ENCODING 9628 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +FC +FC +FC +FC +FC +FC +1C +1C +1C +1C +1C +1C +ENDCHAR +STARTCHAR uni259D +ENCODING 9629 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +1C +1C +1C +1C +1C +1C +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni259E +ENCODING 9630 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +1C +1C +1C +1C +1C +1C +E0 +E0 +E0 +E0 +E0 +E0 +ENDCHAR +STARTCHAR uni259F +ENCODING 9631 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +1C +1C +1C +1C +1C +1C +FC +FC +FC +FC +FC +FC +ENDCHAR +STARTCHAR filledbox +ENCODING 9632 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F8 +F8 +F8 +F8 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR H22073 +ENCODING 9633 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +F8 +88 +88 +88 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR H18543 +ENCODING 9642 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +78 +78 +78 +00 +00 +00 +00 +ENDCHAR +STARTCHAR H18551 +ENCODING 9643 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +78 +48 +48 +78 +00 +00 +00 +00 +ENDCHAR +STARTCHAR filledrect +ENCODING 9644 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +FC +FC +FC +FC +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni25AD +ENCODING 9645 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +FC +84 +84 +FC +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni25AE +ENCODING 9646 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +78 +78 +78 +78 +78 +78 +00 +00 +00 +ENDCHAR +STARTCHAR triagup +ENCODING 9650 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +70 +70 +70 +F8 +F8 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni25B3 +ENCODING 9651 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +20 +50 +50 +50 +88 +88 +F8 +00 +00 +00 +ENDCHAR +STARTCHAR uni25B6 +ENCODING 9654 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +C0 +F0 +F8 +F0 +C0 +00 +00 +00 +ENDCHAR +STARTCHAR uni25B7 +ENCODING 9655 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +C0 +B0 +88 +B0 +C0 +00 +00 +00 +ENDCHAR +STARTCHAR uni25B8 +ENCODING 9656 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +60 +78 +60 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni25B9 +ENCODING 9657 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +60 +58 +60 +00 +00 +00 +00 +ENDCHAR +STARTCHAR triagrt +ENCODING 9658 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +C0 +F0 +FC +F0 +C0 +00 +00 +00 +ENDCHAR +STARTCHAR uni25BB +ENCODING 9659 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +C0 +B0 +8C +B0 +C0 +00 +00 +00 +ENDCHAR +STARTCHAR triagdn +ENCODING 9660 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +F8 +F8 +F8 +70 +70 +70 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni25BD +ENCODING 9661 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +F8 +88 +88 +50 +50 +50 +20 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni25C0 +ENCODING 9664 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +18 +78 +F8 +78 +18 +00 +00 +00 +ENDCHAR +STARTCHAR uni25C1 +ENCODING 9665 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +18 +68 +88 +68 +18 +00 +00 +00 +ENDCHAR +STARTCHAR uni25C2 +ENCODING 9666 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +18 +78 +18 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni25C3 +ENCODING 9667 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +00 +18 +68 +18 +00 +00 +00 +00 +ENDCHAR +STARTCHAR triaglf +ENCODING 9668 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +0C +3C +FC +3C +0C +00 +00 +00 +ENDCHAR +STARTCHAR uni25C5 +ENCODING 9669 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +0C +34 +C4 +34 +0C +00 +00 +00 +ENDCHAR +STARTCHAR uni25C6 +ENCODING 9670 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +20 +70 +F8 +70 +20 +00 +00 +00 +ENDCHAR +STARTCHAR lozenge +ENCODING 9674 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +20 +50 +50 +88 +88 +50 +50 +20 +20 +00 +ENDCHAR +STARTCHAR circle +ENCODING 9675 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR H18533 +ENCODING 9679 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +F8 +F8 +F8 +70 +00 +00 +00 +ENDCHAR +STARTCHAR invbullet +ENCODING 9688 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +FC +FC +FC +FC +CC +84 +84 +CC +FC +FC +FC +FC +ENDCHAR +STARTCHAR invcircle +ENCODING 9689 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +FC +FC +FC +FC +CC +B4 +B4 +CC +FC +FC +FC +FC +ENDCHAR +STARTCHAR openbullet +ENCODING 9702 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +30 +48 +48 +30 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni2639 +ENCODING 9785 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +48 +00 +30 +48 +00 +00 +00 +00 +ENDCHAR +STARTCHAR smileface +ENCODING 9786 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +48 +00 +48 +30 +00 +00 +00 +00 +ENDCHAR +STARTCHAR invsmileface +ENCODING 9787 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +78 +FC +B4 +FC +B4 +CC +78 +00 +00 +00 +ENDCHAR +STARTCHAR sun +ENCODING 9788 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +20 +A8 +70 +D8 +70 +A8 +20 +00 +00 +00 +ENDCHAR +STARTCHAR female +ENCODING 9792 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +00 +00 +70 +88 +88 +88 +70 +20 +70 +20 +ENDCHAR +STARTCHAR uni2641 +ENCODING 9793 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +20 +70 +20 +70 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR male +ENCODING 9794 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +1C +0C +74 +88 +88 +88 +70 +00 +00 +00 +ENDCHAR +STARTCHAR spade +ENCODING 9824 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +78 +FC +FC +FC +78 +30 +78 +00 +00 +00 +ENDCHAR +STARTCHAR club +ENCODING 9827 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +30 +78 +30 +B4 +FC +FC +B4 +30 +78 +00 +00 +00 +ENDCHAR +STARTCHAR heart +ENCODING 9829 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +50 +F8 +F8 +F8 +70 +70 +20 +00 +00 +00 +ENDCHAR +STARTCHAR diamond +ENCODING 9830 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +20 +20 +70 +70 +F8 +70 +70 +20 +20 +00 +00 +00 +ENDCHAR +STARTCHAR uni2669 +ENCODING 9833 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +08 +08 +08 +08 +08 +38 +78 +30 +00 +00 +00 +ENDCHAR +STARTCHAR musicalnote +ENCODING 9834 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +28 +20 +20 +20 +60 +E0 +40 +00 +00 +00 +ENDCHAR +STARTCHAR musicalnotedbl +ENCODING 9835 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +60 +58 +48 +48 +48 +C8 +D8 +18 +00 +00 +00 +ENDCHAR +STARTCHAR uni266C +ENCODING 9836 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +78 +48 +78 +48 +48 +C8 +D8 +18 +00 +00 +00 +ENDCHAR +STARTCHAR uni266D +ENCODING 9837 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +80 +80 +B0 +C8 +88 +90 +E0 +00 +00 +00 +ENDCHAR +STARTCHAR uni266E +ENCODING 9838 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +00 +40 +48 +58 +68 +48 +58 +68 +48 +08 +00 +ENDCHAR +STARTCHAR uni27E8 +ENCODING 10216 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +10 +10 +20 +20 +40 +20 +20 +10 +10 +00 +00 +00 +ENDCHAR +STARTCHAR uni27E9 +ENCODING 10217 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +40 +40 +20 +20 +10 +20 +20 +40 +40 +00 +00 +00 +ENDCHAR +STARTCHAR fi +ENCODING 64257 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +48 +40 +E8 +48 +48 +48 +48 +00 +00 +00 +ENDCHAR +STARTCHAR fl +ENCODING 64258 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +30 +50 +50 +F0 +50 +50 +50 +48 +00 +00 +00 +ENDCHAR +STARTCHAR uniFFFD +ENCODING 65533 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 12 0 -3 +BITMAP +00 +70 +D8 +A8 +E8 +D8 +F8 +D8 +70 +00 +00 +00 +ENDCHAR +ENDFONT diff --git a/gui/themes/fonts/courr12-iso-8859-1.bdf b/gui/themes/fonts/courr12-iso-8859-1.bdf new file mode 100644 index 0000000000..fdd7cbacab --- /dev/null +++ b/gui/themes/fonts/courr12-iso-8859-1.bdf @@ -0,0 +1,2926 @@ +STARTFONT 2.1 +COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT! +COMMENT Generated with 'ucs2any.pl courR12.bdf ../../../fonts/util/map-ISO8859-1 ISO8859-1' +COMMENT from an ISO10646-1 encoded source BDF font. +COMMENT ucs2any.pl by Markus Kuhn <mkuhn@acm.org>, 2000. +FONT -Adobe-Courier-Medium-R-Normal--12-120-75-75-M-70-ISO8859-1 +SIZE 12 75 75 +FONTBOUNDINGBOX 8 14 0 -3 +COMMENT $Xorg: $ +COMMENT ISO10646-1 extension by Markus Kuhn <mkuhn@acm.org>, 2001-03-20 +COMMENT +COMMENT + +COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated. +COMMENT Copyright 1988, 1994 Digital Equipment Corporation. +COMMENT +COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be +COMMENT registered in certain jurisdictions. +COMMENT Permission to use these trademarks is hereby granted only in +COMMENT association with the images described in this file. +COMMENT +COMMENT Permission to use, copy, modify, distribute and sell this software +COMMENT and its documentation for any purpose and without fee is hereby +COMMENT granted, provided that the above copyright notices appear in all +COMMENT copies and that both those copyright notices and this permission +COMMENT notice appear in supporting documentation, and that the names of +COMMENT Adobe Systems and Digital Equipment Corporation not be used in +COMMENT advertising or publicity pertaining to distribution of the software +COMMENT without specific, written prior permission. Adobe Systems and +COMMENT Digital Equipment Corporation make no representations about the +COMMENT suitability of this software for any purpose. It is provided "as +COMMENT is" without express or implied warranty. +COMMENT - +STARTPROPERTIES 26 +FOUNDRY "Adobe" +FAMILY_NAME "Courier" +WEIGHT_NAME "Medium" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 12 +POINT_SIZE 120 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "M" +AVERAGE_WIDTH 70 +CHARSET_REGISTRY "ISO8859" +CHARSET_ENCODING "1" +CAP_HEIGHT 8 +X_HEIGHT 6 +FONT_ASCENT 10 +FONT_DESCENT 3 +FACE_NAME "Courier" +COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved." +NOTICE "No mark" +_DEC_DEVICE_FONTNAMES "PS=Courier" +DEFAULT_CHAR 0 +RELATIVE_SETWIDTH 50 +RELATIVE_WEIGHT 50 +FULL_NAME "Courier" +ENDPROPERTIES +CHARS 192 +STARTCHAR defaultchar +ENCODING 0 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 7 0 0 +BITMAP +AA +00 +82 +00 +82 +00 +AA +ENDCHAR +STARTCHAR space +ENCODING 32 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 1 9 3 0 +BITMAP +80 +80 +80 +80 +80 +80 +80 +00 +80 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 3 3 2 5 +BITMAP +A0 +A0 +A0 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +14 +14 +7E +28 +28 +FC +50 +50 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 10 1 -1 +BITMAP +20 +70 +88 +80 +60 +30 +88 +88 +70 +20 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 8 1 0 +BITMAP +60 +90 +64 +18 +60 +98 +24 +18 +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +38 +48 +40 +22 +74 +88 +8C +72 +ENDCHAR +STARTCHAR quotesingle +ENCODING 39 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 1 3 3 5 +BITMAP +80 +80 +80 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 3 11 3 -2 +BITMAP +20 +40 +40 +80 +80 +80 +80 +80 +40 +40 +20 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 3 11 1 -2 +BITMAP +80 +40 +40 +20 +20 +20 +20 +20 +40 +40 +80 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 5 1 3 +BITMAP +20 +20 +F8 +20 +50 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +20 +20 +F8 +20 +20 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 2 3 1 -1 +BITMAP +40 +40 +80 +ENDCHAR +STARTCHAR hyphen +ENCODING 45 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 1 1 3 +BITMAP +F8 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 1 1 2 0 +BITMAP +80 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 10 1 -1 +BITMAP +04 +08 +08 +10 +10 +20 +20 +40 +40 +80 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +88 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +20 +E0 +20 +20 +20 +20 +20 +20 +F8 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +88 +88 +10 +20 +40 +88 +F8 +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +08 +08 +30 +08 +08 +88 +70 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +08 +18 +28 +28 +48 +88 +FC +08 +1C +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +7C +40 +40 +40 +78 +04 +04 +84 +78 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +38 +40 +80 +80 +F0 +88 +88 +88 +70 +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +F8 +88 +10 +10 +10 +10 +20 +20 +20 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +88 +88 +70 +88 +88 +88 +70 +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +88 +88 +88 +78 +08 +10 +E0 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 1 5 3 0 +BITMAP +80 +00 +00 +00 +80 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 2 6 2 -1 +BITMAP +40 +00 +00 +40 +40 +80 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 4 7 1 0 +BITMAP +10 +20 +40 +80 +40 +20 +10 +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 3 1 2 +BITMAP +F8 +00 +F8 +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 4 7 2 0 +BITMAP +80 +40 +20 +10 +20 +40 +80 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 8 1 0 +BITMAP +70 +88 +08 +10 +20 +20 +00 +20 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 8 1 0 +BITMAP +70 +88 +98 +A8 +A8 +9C +80 +70 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +70 +10 +28 +28 +7C +44 +44 +EE +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F8 +44 +44 +78 +44 +44 +44 +F8 +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 8 1 0 +BITMAP +70 +88 +88 +80 +80 +88 +88 +70 +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F8 +44 +44 +44 +44 +44 +44 +F8 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +FC +44 +50 +70 +50 +40 +44 +FC +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +FC +44 +54 +70 +50 +40 +40 +F0 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 8 1 0 +BITMAP +70 +88 +88 +80 +98 +88 +88 +70 +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +EE +44 +44 +7C +44 +44 +44 +EE +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 8 1 0 +BITMAP +F8 +20 +20 +20 +20 +20 +20 +F8 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 8 1 0 +BITMAP +78 +10 +10 +10 +10 +90 +90 +60 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +EC +48 +50 +60 +70 +48 +44 +E6 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +E0 +40 +40 +40 +40 +44 +44 +FC +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +C6 +6C +6C +54 +54 +54 +44 +EE +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +CE +64 +64 +54 +54 +4C +4C +E4 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 8 1 0 +BITMAP +70 +88 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F8 +4C +44 +4C +78 +40 +40 +F0 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 -1 +BITMAP +70 +88 +88 +88 +88 +88 +88 +70 +18 +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +F8 +44 +44 +78 +48 +44 +44 +E6 +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 8 1 0 +BITMAP +78 +88 +80 +E0 +38 +08 +88 +F0 +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +FE +92 +92 +10 +10 +10 +10 +7C +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +EE +44 +44 +44 +44 +44 +6C +38 +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +EE +44 +44 +6C +28 +28 +38 +10 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +EE +44 +54 +54 +54 +6C +28 +28 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +EE +44 +28 +10 +28 +28 +44 +EE +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +EE +44 +28 +28 +10 +10 +10 +38 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 8 1 0 +BITMAP +F8 +88 +90 +20 +20 +48 +88 +F8 +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 2 11 3 -2 +BITMAP +C0 +80 +80 +80 +80 +80 +80 +80 +80 +80 +C0 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 10 1 -1 +BITMAP +80 +40 +40 +20 +20 +10 +10 +08 +08 +04 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 2 11 2 -2 +BITMAP +C0 +40 +40 +40 +40 +40 +40 +40 +40 +40 +C0 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 3 1 5 +BITMAP +20 +50 +88 +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 1 0 -3 +BITMAP +FE +ENDCHAR +STARTCHAR grave +ENCODING 96 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 2 2 1 7 +BITMAP +80 +40 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 6 1 0 +BITMAP +F0 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +C0 +40 +40 +78 +44 +44 +44 +44 +B8 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 6 1 0 +BITMAP +70 +88 +80 +80 +88 +70 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +18 +08 +08 +78 +88 +88 +88 +88 +74 +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 6 1 0 +BITMAP +70 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +38 +40 +40 +F8 +40 +40 +40 +40 +F0 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 9 1 -3 +BITMAP +74 +88 +88 +88 +88 +78 +08 +08 +70 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +C0 +40 +40 +58 +64 +44 +44 +44 +EE +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +20 +00 +00 +E0 +20 +20 +20 +20 +F8 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 4 12 1 -3 +BITMAP +10 +00 +00 +F0 +10 +10 +10 +10 +10 +10 +10 +E0 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +C0 +40 +40 +4C +50 +60 +50 +48 +C6 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +E0 +20 +20 +20 +20 +20 +20 +20 +FC +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 6 0 0 +BITMAP +E8 +54 +54 +54 +54 +D6 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 6 0 0 +BITMAP +B8 +64 +44 +44 +44 +E6 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 6 1 0 +BITMAP +70 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 9 0 -3 +BITMAP +B8 +44 +44 +44 +44 +78 +40 +40 +E0 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 9 1 -3 +BITMAP +74 +88 +88 +88 +88 +78 +08 +08 +1C +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 6 1 0 +BITMAP +B8 +40 +40 +40 +40 +F0 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 6 1 0 +BITMAP +70 +88 +70 +08 +88 +70 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 8 1 0 +BITMAP +40 +40 +F8 +40 +40 +40 +44 +38 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 6 0 0 +BITMAP +CC +44 +44 +44 +44 +3A +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 6 0 0 +BITMAP +EE +44 +44 +28 +38 +10 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 6 0 0 +BITMAP +EE +44 +54 +54 +28 +28 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 6 0 0 +BITMAP +EE +28 +10 +28 +44 +C6 +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 9 0 -3 +BITMAP +EE +44 +44 +28 +38 +10 +10 +10 +60 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 6 1 0 +BITMAP +F8 +90 +20 +40 +88 +F8 +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 3 10 2 -2 +BITMAP +20 +40 +40 +40 +80 +40 +40 +40 +40 +20 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 1 10 3 -2 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 3 10 2 -2 +BITMAP +80 +40 +40 +40 +20 +40 +40 +40 +40 +80 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 3 1 2 +BITMAP +48 +A8 +90 +ENDCHAR +STARTCHAR space +ENCODING 160 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclamdown +ENCODING 161 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 1 9 3 -3 +BITMAP +80 +00 +00 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR cent +ENCODING 162 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 -1 +BITMAP +20 +20 +70 +A8 +A0 +A8 +70 +20 +20 +ENDCHAR +STARTCHAR sterling +ENCODING 163 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 8 1 0 +BITMAP +30 +48 +40 +F8 +20 +20 +44 +F8 +ENDCHAR +STARTCHAR currency +ENCODING 164 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 6 0 1 +BITMAP +84 +78 +48 +48 +78 +84 +ENDCHAR +STARTCHAR yen +ENCODING 165 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +EE +44 +28 +7C +10 +7C +10 +38 +ENDCHAR +STARTCHAR brokenbar +ENCODING 166 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 1 10 3 -2 +BITMAP +80 +80 +80 +80 +00 +00 +80 +80 +80 +80 +ENDCHAR +STARTCHAR section +ENCODING 167 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 10 1 -1 +BITMAP +78 +48 +60 +90 +88 +48 +30 +90 +90 +F0 +ENDCHAR +STARTCHAR dieresis +ENCODING 168 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 3 1 2 7 +BITMAP +A0 +ENDCHAR +STARTCHAR copyright +ENCODING 169 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +38 +44 +9A +A2 +A2 +9A +44 +38 +ENDCHAR +STARTCHAR ordfeminine +ENCODING 170 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 4 6 1 2 +BITMAP +60 +10 +70 +50 +00 +F0 +ENDCHAR +STARTCHAR guillemotleft +ENCODING 171 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 5 0 1 +BITMAP +24 +48 +90 +48 +24 +ENDCHAR +STARTCHAR logicalnot +ENCODING 172 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 3 1 2 +BITMAP +F8 +08 +08 +ENDCHAR +STARTCHAR hyphen +ENCODING 173 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 1 1 3 +BITMAP +F8 +ENDCHAR +STARTCHAR registered +ENCODING 174 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +38 +44 +BA +AA +B2 +AA +44 +38 +ENDCHAR +STARTCHAR macron +ENCODING 175 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 1 1 7 +BITMAP +F8 +ENDCHAR +STARTCHAR degree +ENCODING 176 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 4 4 1 4 +BITMAP +60 +90 +90 +60 +ENDCHAR +STARTCHAR plusminus +ENCODING 177 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +20 +F8 +20 +00 +F8 +ENDCHAR +STARTCHAR twosuperior +ENCODING 178 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 4 5 1 3 +BITMAP +60 +90 +20 +40 +F0 +ENDCHAR +STARTCHAR threesuperior +ENCODING 179 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 4 5 1 3 +BITMAP +60 +90 +20 +90 +60 +ENDCHAR +STARTCHAR acute +ENCODING 180 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 2 2 3 7 +BITMAP +40 +80 +ENDCHAR +STARTCHAR mu +ENCODING 181 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 9 0 -3 +BITMAP +CC +44 +44 +44 +44 +7A +40 +40 +40 +ENDCHAR +STARTCHAR paragraph +ENCODING 182 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 10 0 -1 +BITMAP +7C +A8 +A8 +A8 +68 +28 +28 +28 +28 +6C +ENDCHAR +STARTCHAR periodcentered +ENCODING 183 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 1 1 3 3 +BITMAP +80 +ENDCHAR +STARTCHAR cedilla +ENCODING 184 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 3 3 2 -3 +BITMAP +40 +20 +C0 +ENDCHAR +STARTCHAR onesuperior +ENCODING 185 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 3 5 2 3 +BITMAP +40 +C0 +40 +40 +E0 +ENDCHAR +STARTCHAR ordmasculine +ENCODING 186 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 4 6 1 2 +BITMAP +60 +90 +90 +60 +00 +F0 +ENDCHAR +STARTCHAR guillemotright +ENCODING 187 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 5 1 1 +BITMAP +90 +48 +24 +48 +90 +ENDCHAR +STARTCHAR onequarter +ENCODING 188 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 8 10 0 -1 +BITMAP +40 +C1 +42 +44 +E8 +12 +26 +4A +8F +02 +ENDCHAR +STARTCHAR onehalf +ENCODING 189 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 8 10 0 -1 +BITMAP +40 +C1 +42 +44 +E8 +16 +29 +42 +84 +0F +ENDCHAR +STARTCHAR threequarters +ENCODING 190 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 8 10 0 -1 +BITMAP +60 +91 +22 +94 +68 +12 +26 +4A +8F +02 +ENDCHAR +STARTCHAR questiondown +ENCODING 191 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 8 1 -2 +BITMAP +20 +00 +20 +20 +40 +80 +88 +70 +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 11 0 0 +BITMAP +20 +10 +00 +70 +10 +28 +28 +7C +44 +44 +EE +ENDCHAR +STARTCHAR Aacute +ENCODING 193 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 11 0 0 +BITMAP +08 +10 +00 +70 +10 +28 +28 +7C +44 +44 +EE +ENDCHAR +STARTCHAR Acircumflex +ENCODING 194 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 11 0 0 +BITMAP +10 +28 +00 +70 +10 +28 +28 +7C +44 +44 +EE +ENDCHAR +STARTCHAR Atilde +ENCODING 195 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 11 0 0 +BITMAP +28 +50 +00 +70 +10 +28 +28 +7C +44 +44 +EE +ENDCHAR +STARTCHAR Adieresis +ENCODING 196 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +28 +00 +70 +10 +28 +28 +7C +44 +44 +EE +ENDCHAR +STARTCHAR Aring +ENCODING 197 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 11 0 0 +BITMAP +10 +28 +10 +70 +10 +28 +28 +7C +44 +44 +EE +ENDCHAR +STARTCHAR AE +ENCODING 198 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +7C +30 +50 +5C +50 +F0 +90 +9C +ENDCHAR +STARTCHAR Ccedilla +ENCODING 199 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 11 1 -3 +BITMAP +70 +88 +88 +80 +80 +88 +88 +70 +20 +10 +60 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +20 +10 +00 +FC +44 +48 +78 +48 +44 +44 +FC +ENDCHAR +STARTCHAR Eacute +ENCODING 201 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +08 +10 +00 +FC +44 +48 +78 +48 +44 +44 +FC +ENDCHAR +STARTCHAR Ecircumflex +ENCODING 202 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +10 +28 +00 +FC +44 +48 +78 +48 +44 +44 +FC +ENDCHAR +STARTCHAR Edieresis +ENCODING 203 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +28 +00 +FC +44 +48 +78 +48 +44 +44 +FC +ENDCHAR +STARTCHAR Igrave +ENCODING 204 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 11 1 0 +BITMAP +40 +20 +00 +F8 +20 +20 +20 +20 +20 +20 +F8 +ENDCHAR +STARTCHAR Iacute +ENCODING 205 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 11 1 0 +BITMAP +10 +20 +00 +F8 +20 +20 +20 +20 +20 +20 +F8 +ENDCHAR +STARTCHAR Icircumflex +ENCODING 206 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 11 1 0 +BITMAP +20 +50 +00 +F8 +20 +20 +20 +20 +20 +20 +F8 +ENDCHAR +STARTCHAR Idieresis +ENCODING 207 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +50 +00 +F8 +20 +20 +20 +20 +20 +20 +F8 +ENDCHAR +STARTCHAR Eth +ENCODING 208 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +F8 +44 +44 +E4 +44 +44 +44 +F8 +ENDCHAR +STARTCHAR Ntilde +ENCODING 209 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 11 0 0 +BITMAP +14 +28 +00 +EE +64 +54 +54 +4C +4C +44 +E4 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 11 1 0 +BITMAP +40 +20 +00 +70 +88 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR Oacute +ENCODING 211 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 11 1 0 +BITMAP +10 +20 +00 +70 +88 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR Ocircumflex +ENCODING 212 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 11 1 0 +BITMAP +20 +50 +00 +70 +88 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR Otilde +ENCODING 213 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 11 1 0 +BITMAP +28 +50 +00 +70 +88 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR Odieresis +ENCODING 214 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +50 +00 +70 +88 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR multiply +ENCODING 215 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +88 +50 +20 +50 +88 +ENDCHAR +STARTCHAR Oslash +ENCODING 216 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 10 1 -1 +BITMAP +08 +70 +98 +A8 +A8 +A8 +A8 +C8 +70 +80 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 11 0 0 +BITMAP +20 +10 +00 +EE +44 +44 +44 +44 +44 +6C +38 +ENDCHAR +STARTCHAR Uacute +ENCODING 218 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 11 0 0 +BITMAP +08 +10 +00 +EE +44 +44 +44 +44 +44 +6C +38 +ENDCHAR +STARTCHAR Ucircumflex +ENCODING 219 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 11 0 0 +BITMAP +10 +28 +00 +EE +44 +44 +44 +44 +44 +6C +38 +ENDCHAR +STARTCHAR Udieresis +ENCODING 220 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +28 +00 +EE +44 +44 +44 +44 +44 +6C +38 +ENDCHAR +STARTCHAR Yacute +ENCODING 221 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 11 0 0 +BITMAP +08 +10 +00 +EE +44 +28 +10 +10 +10 +10 +38 +ENDCHAR +STARTCHAR Thorn +ENCODING 222 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +E0 +40 +78 +44 +44 +78 +40 +E0 +ENDCHAR +STARTCHAR germandbls +ENCODING 223 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +30 +48 +48 +48 +50 +48 +44 +54 +D8 +ENDCHAR +STARTCHAR agrave +ENCODING 224 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +40 +20 +00 +F0 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR aacute +ENCODING 225 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +10 +20 +00 +F0 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR acircumflex +ENCODING 226 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +20 +50 +00 +F0 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR atilde +ENCODING 227 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +28 +50 +00 +F0 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR adieresis +ENCODING 228 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 8 1 0 +BITMAP +50 +00 +F0 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR aring +ENCODING 229 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +20 +50 +20 +F0 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR ae +ENCODING 230 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 6 0 0 +BITMAP +6C +12 +7E +90 +92 +6C +ENDCHAR +STARTCHAR ccedilla +ENCODING 231 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 -3 +BITMAP +70 +88 +80 +80 +88 +70 +20 +10 +60 +ENDCHAR +STARTCHAR egrave +ENCODING 232 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +40 +20 +00 +70 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR eacute +ENCODING 233 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +10 +20 +00 +70 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR ecircumflex +ENCODING 234 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +20 +50 +00 +70 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR edieresis +ENCODING 235 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 8 1 0 +BITMAP +50 +00 +70 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR igrave +ENCODING 236 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +40 +20 +00 +E0 +20 +20 +20 +20 +F8 +ENDCHAR +STARTCHAR iacute +ENCODING 237 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +10 +20 +00 +E0 +20 +20 +20 +20 +F8 +ENDCHAR +STARTCHAR icircumflex +ENCODING 238 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +20 +50 +00 +E0 +20 +20 +20 +20 +F8 +ENDCHAR +STARTCHAR idieresis +ENCODING 239 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 8 1 0 +BITMAP +50 +00 +E0 +20 +20 +20 +20 +F8 +ENDCHAR +STARTCHAR eth +ENCODING 240 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +C0 +38 +60 +90 +78 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR ntilde +ENCODING 241 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +28 +50 +00 +B8 +64 +44 +44 +44 +E6 +ENDCHAR +STARTCHAR ograve +ENCODING 242 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +40 +20 +00 +70 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR oacute +ENCODING 243 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +20 +40 +00 +70 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR ocircumflex +ENCODING 244 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +20 +50 +00 +70 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR otilde +ENCODING 245 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +50 +A0 +00 +70 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR odieresis +ENCODING 246 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 8 1 0 +BITMAP +50 +00 +70 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR divide +ENCODING 247 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +20 +00 +F8 +00 +20 +ENDCHAR +STARTCHAR oslash +ENCODING 248 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 5 8 1 -1 +BITMAP +08 +70 +98 +A8 +A8 +C8 +70 +80 +ENDCHAR +STARTCHAR ugrave +ENCODING 249 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +20 +10 +00 +CC +44 +44 +44 +44 +3A +ENDCHAR +STARTCHAR uacute +ENCODING 250 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +10 +20 +00 +CC +44 +44 +44 +44 +3A +ENDCHAR +STARTCHAR ucircumflex +ENCODING 251 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +10 +28 +00 +CC +44 +44 +44 +44 +3A +ENDCHAR +STARTCHAR udieresis +ENCODING 252 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 8 0 0 +BITMAP +28 +00 +CC +44 +44 +44 +44 +3A +ENDCHAR +STARTCHAR yacute +ENCODING 253 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 12 0 -3 +BITMAP +08 +10 +00 +EE +44 +44 +28 +38 +10 +10 +10 +60 +ENDCHAR +STARTCHAR thorn +ENCODING 254 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 6 12 0 -3 +BITMAP +C0 +40 +40 +78 +44 +44 +44 +44 +78 +40 +40 +E0 +ENDCHAR +STARTCHAR ydieresis +ENCODING 255 +SWIDTH 600 0 +DWIDTH 7 0 +BBX 7 11 0 -3 +BITMAP +28 +00 +EE +44 +44 +28 +38 +10 +10 +10 +60 +ENDCHAR +ENDFONT diff --git a/gui/themes/fonts/fixed5x8-iso-8859-1.bdf b/gui/themes/fonts/fixed5x8-iso-8859-1.bdf new file mode 100644 index 0000000000..80ea041db5 --- /dev/null +++ b/gui/themes/fonts/fixed5x8-iso-8859-1.bdf @@ -0,0 +1,3380 @@ +STARTFONT 2.1 +COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT! +COMMENT Generated with 'ucs2any.pl 5x8.bdf ../../../fonts/util/map-ISO8859-1 ISO8859-1' +COMMENT from an ISO10646-1 encoded source BDF font. +COMMENT ucs2any.pl by Markus Kuhn <mkuhn@acm.org>, 2000. +COMMENT Id: 5x8.bdf,v 1.28 2001-04-03 13:37:48+01 mgk25 Exp mgk25 $ +COMMENT Send bug reports to Markus Kuhn <mkuhn@acm.org> +FONT -Misc-Fixed-Medium-R-Normal--8-80-75-75-C-50-ISO8859-1 +SIZE 11 75 75 +FONTBOUNDINGBOX 5 8 0 -1 +STARTPROPERTIES 21 +FONTNAME_REGISTRY "" +FOUNDRY "Misc" +FAMILY_NAME "Fixed" +WEIGHT_NAME "Medium" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 8 +POINT_SIZE 80 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "C" +AVERAGE_WIDTH 50 +CHARSET_REGISTRY "ISO8859" +CHARSET_ENCODING "1" +FONT_DESCENT 1 +FONT_ASCENT 7 +COPYRIGHT "Public domain font. Share and enjoy." +DEFAULT_CHAR 0 +CAP_HEIGHT 6 +X_HEIGHT 4 +ENDPROPERTIES +CHARS 223 +STARTCHAR defaultchar +ENCODING 0 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +A0 +10 +80 +10 +80 +50 +00 +ENDCHAR +STARTCHAR uni25C6 +ENCODING 1 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +20 +70 +F8 +70 +20 +00 +ENDCHAR +STARTCHAR shade +ENCODING 2 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +50 +A8 +50 +A8 +50 +A8 +50 +A8 +ENDCHAR +STARTCHAR uni2409 +ENCODING 3 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +A0 +A0 +E0 +A0 +A0 +70 +20 +20 +ENDCHAR +STARTCHAR uni240C +ENCODING 4 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +E0 +80 +C0 +B8 +A0 +30 +20 +20 +ENDCHAR +STARTCHAR uni240D +ENCODING 5 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +60 +80 +80 +60 +30 +28 +30 +28 +ENDCHAR +STARTCHAR uni240A +ENCODING 6 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +80 +80 +80 +E0 +38 +20 +30 +20 +ENDCHAR +STARTCHAR degree +ENCODING 7 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +20 +50 +20 +00 +00 +00 +00 +ENDCHAR +STARTCHAR plusminus +ENCODING 8 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +20 +70 +20 +00 +70 +00 +ENDCHAR +STARTCHAR uni2424 +ENCODING 9 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +90 +D0 +B0 +90 +20 +20 +20 +38 +ENDCHAR +STARTCHAR uni240B +ENCODING 10 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +A0 +A0 +A0 +40 +38 +10 +10 +10 +ENDCHAR +STARTCHAR SF040000 +ENCODING 11 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +20 +20 +E0 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF030000 +ENCODING 12 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +E0 +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF010000 +ENCODING 13 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +38 +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF020000 +ENCODING 14 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +20 +20 +38 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF050000 +ENCODING 15 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +20 +20 +F8 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni23BA +ENCODING 16 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +F8 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni23BB +ENCODING 17 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +F8 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF100000 +ENCODING 18 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +F8 +00 +00 +00 +00 +ENDCHAR +STARTCHAR uni23BC +ENCODING 19 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +00 +00 +00 +F8 +00 +ENDCHAR +STARTCHAR uni23BD +ENCODING 20 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +00 +00 +00 +00 +F8 +ENDCHAR +STARTCHAR SF080000 +ENCODING 21 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +20 +20 +38 +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF090000 +ENCODING 22 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +20 +20 +E0 +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF070000 +ENCODING 23 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +20 +20 +F8 +00 +00 +00 +00 +ENDCHAR +STARTCHAR SF060000 +ENCODING 24 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +F8 +20 +20 +20 +20 +ENDCHAR +STARTCHAR SF110000 +ENCODING 25 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +20 +20 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR lessequal +ENCODING 26 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +10 +20 +40 +20 +10 +70 +00 +ENDCHAR +STARTCHAR greaterequal +ENCODING 27 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +40 +20 +10 +20 +40 +70 +00 +ENDCHAR +STARTCHAR pi +ENCODING 28 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +F8 +50 +50 +50 +00 +ENDCHAR +STARTCHAR notequal +ENCODING 29 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +20 +F0 +60 +F0 +40 +00 +ENDCHAR +STARTCHAR sterling +ENCODING 30 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +20 +50 +E0 +40 +50 +A0 +00 +ENDCHAR +STARTCHAR periodcentered +ENCODING 31 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +00 +20 +00 +00 +00 +ENDCHAR +STARTCHAR space +ENCODING 32 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +20 +20 +20 +20 +00 +20 +00 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +50 +50 +50 +00 +00 +00 +00 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +50 +50 +F8 +50 +F8 +50 +50 +00 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +70 +A0 +70 +28 +70 +20 +00 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +40 +50 +20 +50 +10 +00 +00 +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +40 +A0 +A0 +40 +A0 +A0 +50 +00 +ENDCHAR +STARTCHAR quotesingle +ENCODING 39 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +20 +20 +20 +00 +00 +00 +00 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +20 +40 +40 +40 +40 +20 +00 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +40 +20 +20 +20 +20 +40 +00 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +90 +60 +F0 +60 +90 +00 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +20 +20 +F8 +20 +20 +00 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +00 +00 +30 +20 +40 +ENDCHAR +STARTCHAR hyphen +ENCODING 45 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +00 +F0 +00 +00 +00 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +00 +00 +20 +70 +20 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +10 +10 +20 +40 +80 +80 +00 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +20 +50 +50 +50 +50 +20 +00 +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +20 +60 +20 +20 +20 +70 +00 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +60 +90 +10 +60 +80 +F0 +00 +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +F0 +20 +60 +10 +90 +60 +00 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +20 +60 +A0 +F0 +20 +20 +00 +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +F0 +80 +E0 +10 +90 +60 +00 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +60 +80 +E0 +90 +90 +60 +00 +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +F0 +10 +20 +20 +40 +40 +00 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +60 +90 +60 +90 +90 +60 +00 +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +60 +90 +90 +70 +10 +60 +00 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +60 +60 +00 +60 +60 +00 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +30 +30 +00 +30 +20 +40 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +10 +20 +40 +40 +20 +10 +00 +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +F0 +00 +F0 +00 +00 +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +40 +20 +10 +10 +20 +40 +00 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +20 +50 +10 +20 +00 +20 +00 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +30 +48 +98 +A8 +A8 +90 +40 +30 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +60 +90 +90 +F0 +90 +90 +00 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +E0 +90 +E0 +90 +90 +E0 +00 +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +60 +90 +80 +80 +90 +60 +00 +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +E0 +90 +90 +90 +90 +E0 +00 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +F0 +80 +E0 +80 +80 +F0 +00 +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +F0 +80 +E0 +80 +80 +80 +00 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +60 +90 +80 +B0 +90 +60 +00 +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +90 +90 +F0 +90 +90 +90 +00 +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +70 +20 +20 +20 +20 +70 +00 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +70 +20 +20 +20 +A0 +40 +00 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +90 +A0 +C0 +A0 +A0 +90 +00 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +80 +80 +80 +80 +80 +F0 +00 +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +90 +F0 +F0 +90 +90 +90 +00 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +90 +D0 +F0 +B0 +B0 +90 +00 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +60 +90 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +E0 +90 +90 +E0 +80 +80 +00 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +60 +90 +90 +D0 +B0 +60 +10 +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +E0 +90 +90 +E0 +90 +90 +00 +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +60 +90 +40 +20 +90 +60 +00 +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +70 +20 +20 +20 +20 +20 +00 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +90 +90 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +90 +90 +90 +90 +60 +60 +00 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +90 +90 +90 +F0 +F0 +90 +00 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +90 +90 +60 +60 +90 +90 +00 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +88 +88 +50 +20 +20 +20 +00 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +F0 +10 +20 +40 +80 +F0 +00 +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +70 +40 +40 +40 +40 +70 +00 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +80 +80 +40 +20 +10 +10 +00 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +70 +10 +10 +10 +10 +70 +00 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +20 +50 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +00 +00 +00 +00 +F0 +ENDCHAR +STARTCHAR grave +ENCODING 96 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +40 +20 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +70 +90 +90 +70 +00 +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +80 +80 +E0 +90 +90 +E0 +00 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +30 +40 +40 +30 +00 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +10 +10 +70 +90 +90 +70 +00 +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +60 +B0 +C0 +60 +00 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +20 +50 +40 +E0 +40 +40 +00 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +60 +90 +70 +10 +60 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +80 +80 +E0 +90 +90 +90 +00 +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +20 +00 +60 +20 +20 +70 +00 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +10 +00 +10 +10 +10 +50 +20 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +80 +80 +90 +E0 +90 +90 +00 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +60 +20 +20 +20 +20 +70 +00 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +D0 +A8 +A8 +A8 +00 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +E0 +90 +90 +90 +00 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +60 +90 +90 +60 +00 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +E0 +90 +E0 +80 +80 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +70 +90 +70 +10 +10 +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +A0 +D0 +80 +80 +00 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +30 +60 +10 +60 +00 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +40 +40 +E0 +40 +50 +20 +00 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +90 +90 +90 +70 +00 +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +50 +50 +50 +20 +00 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +88 +A8 +A8 +50 +00 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +90 +60 +60 +90 +00 +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +90 +90 +70 +90 +60 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +F0 +20 +40 +F0 +00 +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +30 +40 +20 +C0 +20 +40 +30 +00 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +20 +20 +20 +20 +20 +20 +00 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +C0 +20 +40 +30 +40 +20 +C0 +00 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +50 +A0 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR space +ENCODING 160 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR exclamdown +ENCODING 161 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +20 +00 +20 +20 +20 +20 +00 +ENDCHAR +STARTCHAR cent +ENCODING 162 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +20 +70 +A0 +A0 +70 +20 +ENDCHAR +STARTCHAR sterling +ENCODING 163 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +20 +50 +E0 +40 +50 +A0 +00 +ENDCHAR +STARTCHAR currency +ENCODING 164 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +88 +70 +50 +70 +88 +00 +ENDCHAR +STARTCHAR yen +ENCODING 165 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +88 +50 +F8 +20 +F8 +20 +00 +ENDCHAR +STARTCHAR brokenbar +ENCODING 166 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +20 +20 +00 +20 +20 +20 +00 +ENDCHAR +STARTCHAR section +ENCODING 167 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +70 +80 +E0 +90 +70 +10 +E0 +00 +ENDCHAR +STARTCHAR dieresis +ENCODING 168 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +50 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR copyright +ENCODING 169 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +70 +A8 +C8 +C8 +A8 +70 +00 +ENDCHAR +STARTCHAR ordfeminine +ENCODING 170 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +30 +50 +30 +00 +70 +00 +00 +00 +ENDCHAR +STARTCHAR guillemotleft +ENCODING 171 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +50 +A0 +50 +00 +00 +ENDCHAR +STARTCHAR logicalnot +ENCODING 172 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +00 +70 +10 +10 +00 +ENDCHAR +STARTCHAR hyphen +ENCODING 173 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +00 +70 +00 +00 +00 +ENDCHAR +STARTCHAR registered +ENCODING 174 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +70 +E8 +D8 +E8 +D8 +70 +00 +ENDCHAR +STARTCHAR macron +ENCODING 175 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +70 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR degree +ENCODING 176 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +20 +50 +20 +00 +00 +00 +00 +ENDCHAR +STARTCHAR plusminus +ENCODING 177 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +20 +70 +20 +00 +70 +00 +ENDCHAR +STARTCHAR twosuperior +ENCODING 178 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +50 +10 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR threesuperior +ENCODING 179 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +60 +10 +60 +10 +60 +00 +00 +00 +ENDCHAR +STARTCHAR acute +ENCODING 180 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +20 +40 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR mu +ENCODING 181 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +90 +90 +90 +E0 +80 +ENDCHAR +STARTCHAR paragraph +ENCODING 182 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +78 +E8 +E8 +68 +28 +28 +00 +ENDCHAR +STARTCHAR periodcentered +ENCODING 183 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +00 +20 +00 +00 +00 +ENDCHAR +STARTCHAR cedilla +ENCODING 184 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +00 +00 +00 +20 +40 +ENDCHAR +STARTCHAR onesuperior +ENCODING 185 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +60 +20 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR ordmasculine +ENCODING 186 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +50 +20 +00 +70 +00 +00 +00 +ENDCHAR +STARTCHAR guillemotright +ENCODING 187 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +A0 +50 +A0 +00 +00 +ENDCHAR +STARTCHAR onequarter +ENCODING 188 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +80 +80 +80 +A0 +60 +F0 +20 +00 +ENDCHAR +STARTCHAR onehalf +ENCODING 189 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +80 +80 +A0 +D0 +10 +20 +70 +00 +ENDCHAR +STARTCHAR threequarters +ENCODING 190 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +80 +40 +80 +60 +A0 +F0 +20 +00 +ENDCHAR +STARTCHAR questiondown +ENCODING 191 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +20 +00 +20 +40 +50 +20 +00 +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +40 +20 +60 +90 +F0 +90 +90 +00 +ENDCHAR +STARTCHAR Aacute +ENCODING 193 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +40 +60 +90 +F0 +90 +90 +00 +ENDCHAR +STARTCHAR Acircumflex +ENCODING 194 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +60 +90 +60 +90 +F0 +90 +90 +00 +ENDCHAR +STARTCHAR Atilde +ENCODING 195 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +50 +A0 +60 +90 +F0 +90 +90 +00 +ENDCHAR +STARTCHAR Adieresis +ENCODING 196 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +90 +00 +60 +90 +F0 +90 +90 +00 +ENDCHAR +STARTCHAR Aring +ENCODING 197 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +60 +90 +60 +90 +F0 +90 +90 +00 +ENDCHAR +STARTCHAR AE +ENCODING 198 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +70 +A0 +A0 +F0 +A0 +B0 +00 +ENDCHAR +STARTCHAR Ccedilla +ENCODING 199 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +60 +90 +80 +80 +90 +60 +40 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +40 +20 +F0 +80 +E0 +80 +F0 +00 +ENDCHAR +STARTCHAR Eacute +ENCODING 201 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +40 +F0 +80 +E0 +80 +F0 +00 +ENDCHAR +STARTCHAR Ecircumflex +ENCODING 202 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +60 +90 +F0 +80 +E0 +80 +F0 +00 +ENDCHAR +STARTCHAR Edieresis +ENCODING 203 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +90 +00 +F0 +80 +E0 +80 +F0 +00 +ENDCHAR +STARTCHAR Igrave +ENCODING 204 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +40 +20 +70 +20 +20 +20 +70 +00 +ENDCHAR +STARTCHAR Iacute +ENCODING 205 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +10 +20 +70 +20 +20 +20 +70 +00 +ENDCHAR +STARTCHAR Icircumflex +ENCODING 206 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +50 +70 +20 +20 +20 +70 +00 +ENDCHAR +STARTCHAR Idieresis +ENCODING 207 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +50 +00 +70 +20 +20 +20 +70 +00 +ENDCHAR +STARTCHAR Eth +ENCODING 208 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +70 +48 +E8 +48 +48 +70 +00 +ENDCHAR +STARTCHAR Ntilde +ENCODING 209 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +50 +A0 +90 +D0 +B0 +90 +90 +00 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +40 +20 +60 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR Oacute +ENCODING 211 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +40 +60 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR Ocircumflex +ENCODING 212 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +60 +90 +60 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR Otilde +ENCODING 213 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +50 +A0 +60 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR Odieresis +ENCODING 214 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +90 +00 +60 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR multiply +ENCODING 215 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +00 +50 +20 +50 +00 +ENDCHAR +STARTCHAR Oslash +ENCODING 216 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +70 +B0 +B0 +D0 +D0 +E0 +00 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +40 +20 +90 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR Uacute +ENCODING 218 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +40 +90 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR Ucircumflex +ENCODING 219 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +60 +90 +90 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR Udieresis +ENCODING 220 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +90 +00 +90 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR Yacute +ENCODING 221 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +10 +20 +88 +50 +20 +20 +20 +00 +ENDCHAR +STARTCHAR Thorn +ENCODING 222 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +80 +E0 +90 +90 +E0 +80 +00 +ENDCHAR +STARTCHAR germandbls +ENCODING 223 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +60 +90 +A0 +A0 +90 +A0 +00 +ENDCHAR +STARTCHAR agrave +ENCODING 224 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +40 +20 +00 +70 +90 +90 +70 +00 +ENDCHAR +STARTCHAR aacute +ENCODING 225 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +40 +00 +70 +90 +90 +70 +00 +ENDCHAR +STARTCHAR acircumflex +ENCODING 226 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +50 +00 +70 +90 +90 +70 +00 +ENDCHAR +STARTCHAR atilde +ENCODING 227 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +50 +A0 +00 +70 +90 +90 +70 +00 +ENDCHAR +STARTCHAR adieresis +ENCODING 228 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +50 +00 +70 +90 +90 +70 +00 +ENDCHAR +STARTCHAR aring +ENCODING 229 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +60 +90 +60 +70 +90 +90 +70 +00 +ENDCHAR +STARTCHAR ae +ENCODING 230 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +F0 +68 +B0 +78 +00 +ENDCHAR +STARTCHAR ccedilla +ENCODING 231 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +30 +40 +40 +30 +20 +ENDCHAR +STARTCHAR egrave +ENCODING 232 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +40 +20 +00 +60 +B0 +C0 +60 +00 +ENDCHAR +STARTCHAR eacute +ENCODING 233 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +40 +00 +60 +B0 +C0 +60 +00 +ENDCHAR +STARTCHAR ecircumflex +ENCODING 234 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +60 +90 +00 +60 +B0 +C0 +60 +00 +ENDCHAR +STARTCHAR edieresis +ENCODING 235 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +50 +00 +60 +B0 +C0 +60 +00 +ENDCHAR +STARTCHAR igrave +ENCODING 236 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +40 +20 +00 +60 +20 +20 +70 +00 +ENDCHAR +STARTCHAR iacute +ENCODING 237 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +10 +20 +00 +60 +20 +20 +70 +00 +ENDCHAR +STARTCHAR icircumflex +ENCODING 238 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +50 +00 +60 +20 +20 +70 +00 +ENDCHAR +STARTCHAR idieresis +ENCODING 239 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +50 +00 +60 +20 +20 +70 +00 +ENDCHAR +STARTCHAR eth +ENCODING 240 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +A0 +40 +A0 +10 +70 +90 +60 +00 +ENDCHAR +STARTCHAR ntilde +ENCODING 241 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +50 +A0 +00 +E0 +90 +90 +90 +00 +ENDCHAR +STARTCHAR ograve +ENCODING 242 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +40 +20 +00 +60 +90 +90 +60 +00 +ENDCHAR +STARTCHAR oacute +ENCODING 243 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +40 +00 +60 +90 +90 +60 +00 +ENDCHAR +STARTCHAR ocircumflex +ENCODING 244 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +60 +90 +00 +60 +90 +90 +60 +00 +ENDCHAR +STARTCHAR otilde +ENCODING 245 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +50 +A0 +00 +60 +90 +90 +60 +00 +ENDCHAR +STARTCHAR odieresis +ENCODING 246 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +90 +00 +60 +90 +90 +60 +00 +ENDCHAR +STARTCHAR divide +ENCODING 247 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +20 +00 +70 +00 +20 +00 +ENDCHAR +STARTCHAR oslash +ENCODING 248 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +00 +00 +70 +B0 +D0 +E0 +00 +ENDCHAR +STARTCHAR ugrave +ENCODING 249 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +40 +20 +00 +90 +90 +90 +70 +00 +ENDCHAR +STARTCHAR uacute +ENCODING 250 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +40 +00 +90 +90 +90 +70 +00 +ENDCHAR +STARTCHAR ucircumflex +ENCODING 251 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +60 +90 +00 +90 +90 +90 +70 +00 +ENDCHAR +STARTCHAR udieresis +ENCODING 252 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +90 +00 +90 +90 +90 +70 +00 +ENDCHAR +STARTCHAR yacute +ENCODING 253 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +40 +00 +90 +90 +70 +90 +60 +ENDCHAR +STARTCHAR thorn +ENCODING 254 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +80 +80 +E0 +90 +E0 +80 +80 +ENDCHAR +STARTCHAR ydieresis +ENCODING 255 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +00 +90 +00 +90 +90 +70 +90 +60 +ENDCHAR +ENDFONT diff --git a/gui/themes/fonts/fixed5x8-iso-8859-5.bdf b/gui/themes/fonts/fixed5x8-iso-8859-5.bdf new file mode 100644 index 0000000000..7d0a93cb39 --- /dev/null +++ b/gui/themes/fonts/fixed5x8-iso-8859-5.bdf @@ -0,0 +1,2309 @@ +STARTFONT 2.1 +COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT! +COMMENT Generated with 'ucs2any koi5x8-ucs.bdf /usr/share/fonts/X11/util/map-ISO8859-5 ISO8859-5' +COMMENT from an ISO10646-1 encoded source BDF font. +COMMENT ucs2any by Ben Collver <collver1@attbi.com>, 2003, based on +COMMENT ucs2any.pl by Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>, 2000. +COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT! +COMMENT Generated with 'ucs2any.pl 5x8.bdf ../xcyr-2.3/tryfont/KOI8-C.TXT KOI8-C' +COMMENT from an ISO10646-1 encoded source BDF font. +COMMENT ucs2any.pl by Markus Kuhn <mkuhn@acm.org>, 1999. +COMMENT $Id$ +COMMENT Send bug reports to Markus Kuhn <mkuhn@acm.org> +COMMENT Changes 1999 by Serge Winitzki. +COMMENT $XFree86$ +FONT -Misc-Fixed-Medium-R-Normal--8-80-75-75-C-50-ISO8859-5 +SIZE 11 75 75 +FONTBOUNDINGBOX 5 8 0 -1 +STARTPROPERTIES 22 +FONTNAME_REGISTRY "" +FOUNDRY "Misc" +FAMILY_NAME "Fixed" +WEIGHT_NAME "Medium" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 8 +POINT_SIZE 80 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "C" +AVERAGE_WIDTH 50 +CHARSET_REGISTRY "ISO8859" +CHARSET_ENCODING "5" +FONT_DESCENT 1 +FONT_ASCENT 7 +COPYRIGHT "Public domain font. Share and enjoy." +DEFAULT_CHAR 0 +CAP_HEIGHT 6 +X_HEIGHT 4 +_XFREE86_GLYPH_RANGES "0_126 149 152_154 156_158 163 179 191_255" +ENDPROPERTIES +CHARS 185 +STARTCHAR uni25C6 +ENCODING 1 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 0 +BITMAP +20 +70 +F8 +70 +20 +ENDCHAR +STARTCHAR uni2592 +ENCODING 2 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +50 +A8 +50 +A8 +50 +A8 +50 +A8 +ENDCHAR +STARTCHAR uni00B1 +ENCODING 8 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 0 +BITMAP +20 +70 +20 +00 +70 +ENDCHAR +STARTCHAR uni2518 +ENCODING 11 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 3 +BITMAP +20 +20 +20 +E0 +ENDCHAR +STARTCHAR uni2510 +ENCODING 12 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 -1 +BITMAP +E0 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni250C +ENCODING 13 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 -1 +BITMAP +38 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2514 +ENCODING 14 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 3 +BITMAP +20 +20 +20 +38 +ENDCHAR +STARTCHAR uni253C +ENCODING 15 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +20 +20 +F8 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2500 +ENCODING 18 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 1 0 3 +BITMAP +F8 +ENDCHAR +STARTCHAR uni251C +ENCODING 21 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +20 +20 +38 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2524 +ENCODING 22 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +20 +20 +E0 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2534 +ENCODING 23 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 3 +BITMAP +20 +20 +20 +F8 +ENDCHAR +STARTCHAR uni252C +ENCODING 24 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 -1 +BITMAP +F8 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2502 +ENCODING 25 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +20 +20 +20 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni2264 +ENCODING 26 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +10 +20 +40 +20 +10 +70 +ENDCHAR +STARTCHAR uni2265 +ENCODING 27 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +40 +20 +10 +20 +40 +70 +ENDCHAR +STARTCHAR uni03C0 +ENCODING 28 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +F8 +50 +50 +50 +ENDCHAR +STARTCHAR uni2260 +ENCODING 29 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 0 +BITMAP +20 +F0 +60 +F0 +40 +ENDCHAR +STARTCHAR uni00A3 +ENCODING 30 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +10 +20 +40 +20 +10 +70 +ENDCHAR +STARTCHAR uni00B7 +ENCODING 31 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +40 +20 +10 +20 +40 +70 +ENDCHAR +STARTCHAR uni0020 +ENCODING 32 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 0 0 0 0 +BITMAP +ENDCHAR +STARTCHAR uni0021 +ENCODING 33 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +20 +20 +20 +20 +00 +20 +ENDCHAR +STARTCHAR uni0022 +ENCODING 34 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 3 0 3 +BITMAP +50 +50 +50 +ENDCHAR +STARTCHAR uni0023 +ENCODING 35 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 7 0 0 +BITMAP +50 +50 +F8 +50 +F8 +50 +50 +ENDCHAR +STARTCHAR uni0024 +ENCODING 36 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 7 0 0 +BITMAP +20 +70 +A0 +70 +28 +70 +20 +ENDCHAR +STARTCHAR uni0025 +ENCODING 37 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 1 +BITMAP +40 +50 +20 +50 +10 +ENDCHAR +STARTCHAR uni0026 +ENCODING 38 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 7 0 0 +BITMAP +40 +A0 +A0 +40 +A0 +A0 +50 +ENDCHAR +STARTCHAR uni0027 +ENCODING 39 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 3 0 3 +BITMAP +20 +20 +20 +ENDCHAR +STARTCHAR uni0028 +ENCODING 40 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +20 +40 +40 +40 +40 +20 +ENDCHAR +STARTCHAR uni0029 +ENCODING 41 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +40 +20 +20 +20 +20 +40 +ENDCHAR +STARTCHAR uni002A +ENCODING 42 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 0 +BITMAP +90 +60 +F0 +60 +90 +ENDCHAR +STARTCHAR uni002B +ENCODING 43 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 0 +BITMAP +20 +20 +F8 +20 +20 +ENDCHAR +STARTCHAR uni002C +ENCODING 44 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 3 0 -1 +BITMAP +30 +20 +40 +ENDCHAR +STARTCHAR uni002D +ENCODING 45 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 1 0 2 +BITMAP +F0 +ENDCHAR +STARTCHAR uni002E +ENCODING 46 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 3 0 -1 +BITMAP +20 +70 +20 +ENDCHAR +STARTCHAR uni002F +ENCODING 47 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +10 +10 +20 +40 +80 +80 +ENDCHAR +STARTCHAR uni0030 +ENCODING 48 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +20 +50 +50 +50 +50 +20 +ENDCHAR +STARTCHAR uni0031 +ENCODING 49 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +20 +60 +20 +20 +20 +70 +ENDCHAR +STARTCHAR uni0032 +ENCODING 50 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +60 +90 +10 +60 +80 +F0 +ENDCHAR +STARTCHAR uni0033 +ENCODING 51 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +F0 +20 +60 +10 +90 +60 +ENDCHAR +STARTCHAR uni0034 +ENCODING 52 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +20 +60 +A0 +F0 +20 +20 +ENDCHAR +STARTCHAR uni0035 +ENCODING 53 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +F0 +80 +E0 +10 +90 +60 +ENDCHAR +STARTCHAR uni0036 +ENCODING 54 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +60 +80 +E0 +90 +90 +60 +ENDCHAR +STARTCHAR uni0037 +ENCODING 55 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +F0 +10 +20 +20 +40 +40 +ENDCHAR +STARTCHAR uni0038 +ENCODING 56 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +60 +90 +60 +90 +90 +60 +ENDCHAR +STARTCHAR uni0039 +ENCODING 57 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +60 +90 +90 +70 +10 +60 +ENDCHAR +STARTCHAR uni003A +ENCODING 58 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 0 +BITMAP +60 +60 +00 +60 +60 +ENDCHAR +STARTCHAR uni003B +ENCODING 59 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 -1 +BITMAP +30 +30 +00 +30 +20 +40 +ENDCHAR +STARTCHAR uni003C +ENCODING 60 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +10 +20 +40 +40 +20 +10 +ENDCHAR +STARTCHAR uni003D +ENCODING 61 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 3 0 1 +BITMAP +F0 +00 +F0 +ENDCHAR +STARTCHAR uni003E +ENCODING 62 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +40 +20 +10 +10 +20 +40 +ENDCHAR +STARTCHAR uni003F +ENCODING 63 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +20 +50 +10 +20 +00 +20 +ENDCHAR +STARTCHAR uni0040 +ENCODING 64 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 8 0 -1 +BITMAP +30 +48 +98 +A8 +A8 +90 +40 +30 +ENDCHAR +STARTCHAR uni0041 +ENCODING 65 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +60 +90 +90 +F0 +90 +90 +ENDCHAR +STARTCHAR uni0042 +ENCODING 66 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +E0 +90 +E0 +90 +90 +E0 +ENDCHAR +STARTCHAR uni0043 +ENCODING 67 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +60 +90 +80 +80 +90 +60 +ENDCHAR +STARTCHAR uni0044 +ENCODING 68 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +E0 +90 +90 +90 +90 +E0 +ENDCHAR +STARTCHAR uni0045 +ENCODING 69 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +F0 +80 +E0 +80 +80 +F0 +ENDCHAR +STARTCHAR uni0046 +ENCODING 70 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +F0 +80 +E0 +80 +80 +80 +ENDCHAR +STARTCHAR uni0047 +ENCODING 71 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +60 +90 +80 +B0 +90 +60 +ENDCHAR +STARTCHAR uni0048 +ENCODING 72 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +90 +90 +F0 +90 +90 +90 +ENDCHAR +STARTCHAR uni0049 +ENCODING 73 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +70 +20 +20 +20 +20 +70 +ENDCHAR +STARTCHAR uni004A +ENCODING 74 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +70 +20 +20 +20 +A0 +40 +ENDCHAR +STARTCHAR uni004B +ENCODING 75 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +90 +A0 +C0 +A0 +A0 +90 +ENDCHAR +STARTCHAR uni004C +ENCODING 76 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +80 +80 +80 +80 +80 +F0 +ENDCHAR +STARTCHAR uni004D +ENCODING 77 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +90 +F0 +F0 +90 +90 +90 +ENDCHAR +STARTCHAR uni004E +ENCODING 78 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +90 +D0 +F0 +B0 +B0 +90 +ENDCHAR +STARTCHAR uni004F +ENCODING 79 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +60 +90 +90 +90 +90 +60 +ENDCHAR +STARTCHAR uni0050 +ENCODING 80 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +E0 +90 +90 +E0 +80 +80 +ENDCHAR +STARTCHAR uni0051 +ENCODING 81 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +90 +D0 +B0 +60 +10 +ENDCHAR +STARTCHAR uni0052 +ENCODING 82 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +E0 +90 +90 +E0 +90 +90 +ENDCHAR +STARTCHAR uni0053 +ENCODING 83 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +60 +90 +40 +20 +90 +60 +ENDCHAR +STARTCHAR uni0054 +ENCODING 84 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +70 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni0055 +ENCODING 85 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +90 +90 +90 +90 +90 +60 +ENDCHAR +STARTCHAR uni0056 +ENCODING 86 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +90 +90 +90 +90 +60 +60 +ENDCHAR +STARTCHAR uni0057 +ENCODING 87 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +90 +90 +90 +F0 +F0 +90 +ENDCHAR +STARTCHAR uni0058 +ENCODING 88 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +90 +90 +60 +60 +90 +90 +ENDCHAR +STARTCHAR uni0059 +ENCODING 89 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +88 +88 +50 +20 +20 +20 +ENDCHAR +STARTCHAR uni005A +ENCODING 90 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +F0 +10 +20 +40 +80 +F0 +ENDCHAR +STARTCHAR uni005B +ENCODING 91 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +70 +40 +40 +40 +40 +70 +ENDCHAR +STARTCHAR uni005C +ENCODING 92 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +80 +80 +40 +20 +10 +10 +ENDCHAR +STARTCHAR uni005D +ENCODING 93 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +70 +10 +10 +10 +10 +70 +ENDCHAR +STARTCHAR uni005E +ENCODING 94 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 2 0 4 +BITMAP +20 +50 +ENDCHAR +STARTCHAR uni005F +ENCODING 95 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 1 0 -1 +BITMAP +F0 +ENDCHAR +STARTCHAR uni0060 +ENCODING 96 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 2 0 4 +BITMAP +40 +20 +ENDCHAR +STARTCHAR uni0061 +ENCODING 97 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +70 +90 +90 +70 +ENDCHAR +STARTCHAR uni0062 +ENCODING 98 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +80 +80 +E0 +90 +90 +E0 +ENDCHAR +STARTCHAR uni0063 +ENCODING 99 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +30 +40 +40 +30 +ENDCHAR +STARTCHAR uni0064 +ENCODING 100 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +10 +10 +70 +90 +90 +70 +ENDCHAR +STARTCHAR uni0065 +ENCODING 101 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +60 +B0 +C0 +60 +ENDCHAR +STARTCHAR uni0066 +ENCODING 102 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +20 +50 +40 +E0 +40 +40 +ENDCHAR +STARTCHAR uni0067 +ENCODING 103 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 -1 +BITMAP +60 +90 +70 +10 +60 +ENDCHAR +STARTCHAR uni0068 +ENCODING 104 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +80 +80 +E0 +90 +90 +90 +ENDCHAR +STARTCHAR uni0069 +ENCODING 105 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +20 +00 +60 +20 +20 +70 +ENDCHAR +STARTCHAR uni006A +ENCODING 106 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +10 +00 +10 +10 +10 +50 +20 +ENDCHAR +STARTCHAR uni006B +ENCODING 107 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +80 +80 +90 +E0 +90 +90 +ENDCHAR +STARTCHAR uni006C +ENCODING 108 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +60 +20 +20 +20 +20 +70 +ENDCHAR +STARTCHAR uni006D +ENCODING 109 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +D0 +A8 +A8 +A8 +ENDCHAR +STARTCHAR uni006E +ENCODING 110 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +E0 +90 +90 +90 +ENDCHAR +STARTCHAR uni006F +ENCODING 111 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +60 +90 +90 +60 +ENDCHAR +STARTCHAR uni0070 +ENCODING 112 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 -1 +BITMAP +E0 +90 +E0 +80 +80 +ENDCHAR +STARTCHAR uni0071 +ENCODING 113 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 -1 +BITMAP +70 +90 +70 +10 +10 +ENDCHAR +STARTCHAR uni0072 +ENCODING 114 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +A0 +D0 +80 +80 +ENDCHAR +STARTCHAR uni0073 +ENCODING 115 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +30 +60 +10 +60 +ENDCHAR +STARTCHAR uni0074 +ENCODING 116 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +40 +40 +E0 +40 +50 +20 +ENDCHAR +STARTCHAR uni0075 +ENCODING 117 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +90 +90 +90 +70 +ENDCHAR +STARTCHAR uni0076 +ENCODING 118 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +50 +50 +50 +20 +ENDCHAR +STARTCHAR uni0077 +ENCODING 119 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +88 +A8 +A8 +50 +ENDCHAR +STARTCHAR uni0078 +ENCODING 120 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +90 +60 +60 +90 +ENDCHAR +STARTCHAR uni0079 +ENCODING 121 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 -1 +BITMAP +90 +90 +70 +90 +60 +ENDCHAR +STARTCHAR uni007A +ENCODING 122 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +F0 +20 +40 +F0 +ENDCHAR +STARTCHAR uni007B +ENCODING 123 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 7 0 0 +BITMAP +30 +40 +20 +C0 +20 +40 +30 +ENDCHAR +STARTCHAR uni007C +ENCODING 124 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +20 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni007D +ENCODING 125 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 7 0 0 +BITMAP +C0 +20 +40 +30 +40 +20 +C0 +ENDCHAR +STARTCHAR uni007E +ENCODING 126 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 2 0 4 +BITMAP +50 +A0 +ENDCHAR +STARTCHAR uni0401 +ENCODING 161 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +F0 +80 +E0 +80 +80 +F0 +ENDCHAR +STARTCHAR uni0410 +ENCODING 176 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +60 +90 +90 +F0 +90 +90 +ENDCHAR +STARTCHAR uni0411 +ENCODING 177 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +E0 +80 +E0 +90 +90 +E0 +ENDCHAR +STARTCHAR uni0412 +ENCODING 178 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +E0 +90 +E0 +90 +90 +E0 +ENDCHAR +STARTCHAR uni0413 +ENCODING 179 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +F0 +90 +80 +80 +80 +80 +ENDCHAR +STARTCHAR uni0414 +ENCODING 180 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +A0 +A0 +A0 +A0 +F0 +90 +ENDCHAR +STARTCHAR uni0415 +ENCODING 181 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +F0 +80 +E0 +80 +80 +F0 +ENDCHAR +STARTCHAR uni0416 +ENCODING 182 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +A8 +A8 +70 +A8 +A8 +A8 +ENDCHAR +STARTCHAR uni0417 +ENCODING 183 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +60 +90 +20 +10 +90 +60 +ENDCHAR +STARTCHAR uni0418 +ENCODING 184 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +90 +90 +B0 +D0 +90 +90 +ENDCHAR +STARTCHAR uni0419 +ENCODING 185 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 7 0 0 +BITMAP +60 +90 +90 +B0 +D0 +90 +90 +ENDCHAR +STARTCHAR uni041A +ENCODING 186 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +90 +A0 +C0 +A0 +90 +90 +ENDCHAR +STARTCHAR uni041B +ENCODING 187 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +30 +50 +50 +50 +50 +90 +ENDCHAR +STARTCHAR uni041C +ENCODING 188 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +90 +F0 +F0 +90 +90 +90 +ENDCHAR +STARTCHAR uni041D +ENCODING 189 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +90 +90 +F0 +90 +90 +90 +ENDCHAR +STARTCHAR uni041E +ENCODING 190 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +60 +90 +90 +90 +90 +60 +ENDCHAR +STARTCHAR uni041F +ENCODING 191 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +F0 +90 +90 +90 +90 +90 +ENDCHAR +STARTCHAR uni0420 +ENCODING 192 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +E0 +90 +90 +E0 +80 +80 +ENDCHAR +STARTCHAR uni0421 +ENCODING 193 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +60 +90 +80 +80 +90 +60 +ENDCHAR +STARTCHAR uni0422 +ENCODING 194 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +70 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni0423 +ENCODING 195 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +90 +90 +90 +70 +10 +E0 +ENDCHAR +STARTCHAR uni0424 +ENCODING 196 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +20 +70 +A8 +A8 +70 +20 +ENDCHAR +STARTCHAR uni0425 +ENCODING 197 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +50 +50 +20 +20 +50 +50 +ENDCHAR +STARTCHAR uni0426 +ENCODING 198 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +A0 +A0 +A0 +A0 +A0 +F0 +10 +ENDCHAR +STARTCHAR uni0427 +ENCODING 199 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +50 +50 +50 +30 +10 +10 +ENDCHAR +STARTCHAR uni0428 +ENCODING 200 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +A8 +A8 +A8 +A8 +A8 +F8 +ENDCHAR +STARTCHAR uni0429 +ENCODING 201 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +A8 +A8 +A8 +A8 +A8 +F8 +08 +ENDCHAR +STARTCHAR uni042A +ENCODING 202 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +E0 +20 +30 +28 +28 +30 +ENDCHAR +STARTCHAR uni042B +ENCODING 203 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +88 +88 +C8 +A8 +A8 +C8 +ENDCHAR +STARTCHAR uni042C +ENCODING 204 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +40 +40 +60 +50 +50 +60 +ENDCHAR +STARTCHAR uni042D +ENCODING 205 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +E0 +10 +70 +10 +10 +E0 +ENDCHAR +STARTCHAR uni042E +ENCODING 206 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +90 +A8 +E8 +A8 +A8 +90 +ENDCHAR +STARTCHAR uni042F +ENCODING 207 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +70 +90 +90 +70 +90 +90 +ENDCHAR +STARTCHAR uni0430 +ENCODING 208 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +70 +90 +90 +70 +ENDCHAR +STARTCHAR uni0431 +ENCODING 209 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 7 0 0 +BITMAP +10 +60 +80 +E0 +90 +90 +60 +ENDCHAR +STARTCHAR uni0432 +ENCODING 210 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +E0 +E0 +90 +E0 +ENDCHAR +STARTCHAR uni0433 +ENCODING 211 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +70 +40 +40 +40 +ENDCHAR +STARTCHAR uni0434 +ENCODING 212 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 -1 +BITMAP +70 +50 +90 +F0 +90 +ENDCHAR +STARTCHAR uni0435 +ENCODING 213 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +60 +B0 +C0 +60 +ENDCHAR +STARTCHAR uni0436 +ENCODING 214 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +A8 +70 +A8 +A8 +ENDCHAR +STARTCHAR uni0437 +ENCODING 215 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +70 +30 +10 +60 +ENDCHAR +STARTCHAR uni0438 +ENCODING 216 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +90 +B0 +D0 +90 +ENDCHAR +STARTCHAR uni0439 +ENCODING 217 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +60 +00 +90 +B0 +D0 +90 +ENDCHAR +STARTCHAR uni043A +ENCODING 218 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +90 +E0 +A0 +90 +ENDCHAR +STARTCHAR uni043B +ENCODING 219 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +30 +50 +50 +90 +ENDCHAR +STARTCHAR uni043C +ENCODING 220 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +88 +D8 +A8 +A8 +ENDCHAR +STARTCHAR uni043D +ENCODING 221 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +90 +F0 +90 +90 +ENDCHAR +STARTCHAR uni043E +ENCODING 222 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +60 +90 +90 +60 +ENDCHAR +STARTCHAR uni043F +ENCODING 223 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +F0 +90 +90 +90 +ENDCHAR +STARTCHAR uni0440 +ENCODING 224 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 -1 +BITMAP +E0 +90 +90 +E0 +80 +ENDCHAR +STARTCHAR uni0441 +ENCODING 225 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +30 +40 +40 +30 +ENDCHAR +STARTCHAR uni0442 +ENCODING 226 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +70 +20 +20 +20 +ENDCHAR +STARTCHAR uni0443 +ENCODING 227 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 -1 +BITMAP +90 +90 +50 +20 +40 +ENDCHAR +STARTCHAR uni0444 +ENCODING 228 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +20 +70 +50 +50 +70 +20 +ENDCHAR +STARTCHAR uni0445 +ENCODING 229 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +90 +60 +60 +90 +ENDCHAR +STARTCHAR uni0446 +ENCODING 230 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 -1 +BITMAP +90 +90 +90 +F0 +10 +ENDCHAR +STARTCHAR uni0447 +ENCODING 231 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +90 +90 +70 +10 +ENDCHAR +STARTCHAR uni0448 +ENCODING 232 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +A8 +A8 +A8 +F8 +ENDCHAR +STARTCHAR uni0449 +ENCODING 233 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 -1 +BITMAP +A8 +A8 +A8 +F8 +08 +ENDCHAR +STARTCHAR uni044A +ENCODING 234 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +C0 +60 +50 +60 +ENDCHAR +STARTCHAR uni044B +ENCODING 235 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +90 +D0 +B0 +D0 +ENDCHAR +STARTCHAR uni044C +ENCODING 236 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +80 +E0 +90 +E0 +ENDCHAR +STARTCHAR uni044D +ENCODING 237 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +60 +30 +10 +60 +ENDCHAR +STARTCHAR uni044E +ENCODING 238 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +A0 +D0 +D0 +A0 +ENDCHAR +STARTCHAR uni044F +ENCODING 239 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 4 0 0 +BITMAP +30 +50 +30 +50 +ENDCHAR +STARTCHAR uni0451 +ENCODING 241 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 6 0 0 +BITMAP +A0 +00 +60 +B0 +C0 +60 +ENDCHAR +STARTCHAR uni0459 +ENCODING 249 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 0 0 0 0 +BITMAP +ENDCHAR +STARTCHAR uni045A +ENCODING 250 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 3 0 3 +BITMAP +20 +50 +20 +ENDCHAR +STARTCHAR uni045B +ENCODING 251 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 1 0 2 +BITMAP +20 +ENDCHAR +STARTCHAR uni045C +ENCODING 252 +SWIDTH 436 0 +DWIDTH 5 0 +BBX 5 5 0 2 +BITMAP +20 +50 +10 +20 +70 +ENDCHAR +ENDFONT diff --git a/gui/themes/fonts/helvB12-iso-8859-1.bdf b/gui/themes/fonts/helvB12-iso-8859-1.bdf new file mode 100644 index 0000000000..1eabe21c57 --- /dev/null +++ b/gui/themes/fonts/helvB12-iso-8859-1.bdf @@ -0,0 +1,3059 @@ +STARTFONT 2.1 +COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT! +COMMENT Generated with 'ucs2any.pl helvB12.bdf ../../../fonts/util/map-ISO8859-1 ISO8859-1' +COMMENT from an ISO10646-1 encoded source BDF font. +COMMENT ucs2any.pl by Markus Kuhn <mkuhn@acm.org>, 2000. +FONT -Adobe-Helvetica-Bold-R-Normal--12-120-75-75-P-70-ISO8859-1 +SIZE 12 75 75 +FONTBOUNDINGBOX 13 15 -1 -3 +COMMENT $Xorg: $ +COMMENT ISO10646-1 extension by Markus Kuhn <mkuhn@acm.org>, 2001-03-20 +COMMENT +COMMENT + +COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated. +COMMENT Copyright 1988, 1994 Digital Equipment Corporation. +COMMENT +COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be +COMMENT registered in certain jurisdictions. +COMMENT Permission to use these trademarks is hereby granted only in +COMMENT association with the images described in this file. +COMMENT +COMMENT Permission to use, copy, modify, distribute and sell this software +COMMENT and its documentation for any purpose and without fee is hereby +COMMENT granted, provided that the above copyright notices appear in all +COMMENT copies and that both those copyright notices and this permission +COMMENT notice appear in supporting documentation, and that the names of +COMMENT Adobe Systems and Digital Equipment Corporation not be used in +COMMENT advertising or publicity pertaining to distribution of the software +COMMENT without specific, written prior permission. Adobe Systems and +COMMENT Digital Equipment Corporation make no representations about the +COMMENT suitability of this software for any purpose. It is provided "as +COMMENT is" without express or implied warranty. +COMMENT - +STARTPROPERTIES 26 +FOUNDRY "Adobe" +FAMILY_NAME "Helvetica" +WEIGHT_NAME "Bold" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 12 +POINT_SIZE 120 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "P" +AVERAGE_WIDTH 70 +CHARSET_REGISTRY "ISO8859" +CHARSET_ENCODING "1" +CAP_HEIGHT 9 +X_HEIGHT 7 +FONT_ASCENT 11 +FONT_DESCENT 3 +FACE_NAME "Helvetica Bold" +COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved." +NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. " +_DEC_DEVICE_FONTNAMES "PS=Helvetica-Bold" +DEFAULT_CHAR 0 +RELATIVE_SETWIDTH 50 +RELATIVE_WEIGHT 70 +FULL_NAME "Helvetica Bold" +ENDPROPERTIES +CHARS 192 +STARTCHAR defaultchar +ENCODING 0 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +AA +00 +82 +00 +82 +00 +82 +00 +AA +ENDCHAR +STARTCHAR space +ENCODING 32 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 9 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +80 +00 +C0 +C0 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 474 0 +DWIDTH 5 0 +BBX 3 3 1 6 +BITMAP +A0 +A0 +A0 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +14 +14 +7E +28 +28 +FC +50 +50 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 11 0 -2 +BITMAP +10 +78 +D4 +D0 +78 +1C +94 +D4 +78 +10 +10 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 889 0 +DWIDTH 12 0 +BBX 11 9 0 0 +BITMAP +7100 +DB00 +DA00 +7400 +0400 +09C0 +0B60 +1B60 +11C0 +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 9 0 0 +BITMAP +3800 +6C00 +6C00 +3800 +7900 +CF00 +C600 +CF00 +7980 +ENDCHAR +STARTCHAR quotesingle +ENCODING 39 +SWIDTH 238 0 +DWIDTH 3 0 +BBX 1 3 1 6 +BITMAP +80 +80 +80 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 4 12 1 -3 +BITMAP +30 +60 +60 +C0 +C0 +C0 +C0 +C0 +C0 +60 +60 +30 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 4 12 1 -3 +BITMAP +C0 +60 +60 +30 +30 +30 +30 +30 +30 +60 +60 +C0 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 389 0 +DWIDTH 6 0 +BBX 5 4 0 5 +BITMAP +20 +F8 +70 +50 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 5 0 1 +BITMAP +30 +30 +FC +30 +30 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 4 1 -2 +BITMAP +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR hyphen +ENCODING 45 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 0 3 +BITMAP +F0 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 2 1 0 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 9 0 0 +BITMAP +30 +30 +20 +60 +60 +40 +40 +C0 +C0 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 4 9 0 0 +BITMAP +30 +F0 +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +0C +18 +30 +60 +C0 +C0 +FC +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +0C +38 +0C +0C +0C +CC +78 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +0C +1C +2C +2C +4C +8C +FE +0C +0C +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +7C +60 +C0 +F8 +0C +0C +CC +CC +78 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +C0 +C0 +F8 +CC +CC +CC +78 +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +FC +0C +18 +18 +30 +30 +30 +60 +60 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +CC +78 +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +CC +CC +7C +0C +0C +CC +78 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 7 1 0 +BITMAP +C0 +C0 +00 +00 +00 +C0 +C0 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 9 1 -2 +BITMAP +C0 +C0 +00 +00 +00 +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +18 +70 +C0 +70 +18 +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 3 0 2 +BITMAP +FC +00 +FC +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +C0 +70 +18 +70 +C0 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +78 +CC +CC +18 +30 +30 +00 +30 +30 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 975 0 +DWIDTH 12 0 +BBX 10 10 1 -1 +BITMAP +1F00 +6080 +4040 +8D40 +9240 +A240 +A680 +9B00 +4000 +3E00 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +18 +3C +24 +66 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +FC +C6 +C6 +C6 +FC +C6 +C6 +C6 +FC +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 9 1 0 +BITMAP +3C +66 +C0 +C0 +C0 +C0 +C0 +66 +3C +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +F8 +CC +C6 +C6 +C6 +C6 +C6 +CC +F8 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +3E +63 +C0 +C0 +CF +C3 +C3 +63 +3D +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +C6 +C6 +C6 +C6 +FE +C6 +C6 +C6 +C6 +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 9 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +0C +0C +0C +0C +0C +0C +CC +CC +78 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 9 1 0 +BITMAP +C6 +CC +D8 +F0 +F0 +D8 +CC +C6 +C3 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 833 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +C180 +C180 +E380 +E380 +F780 +D580 +DD80 +C980 +C980 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +C6 +E6 +E6 +D6 +D6 +CE +CE +C6 +C6 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 9 1 0 +BITMAP +FC +C6 +C6 +C6 +FC +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +3C +66 +C3 +C3 +C3 +CB +CF +66 +3F +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +FC +C6 +C6 +C6 +FC +CC +C6 +C6 +C6 +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +7C +C6 +C6 +70 +1C +0E +C6 +C6 +7C +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +FF +18 +18 +18 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +C3 +C3 +66 +66 +66 +24 +3C +18 +18 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 9 0 0 +BITMAP +CCC0 +CCC0 +CCC0 +4C80 +6D80 +6D80 +3300 +3300 +3300 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +C3 +C3 +66 +3C +18 +3C +66 +C3 +C3 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +C3 +C3 +66 +66 +3C +18 +18 +18 +18 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +FE +06 +0C +18 +30 +30 +60 +C0 +FE +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 12 1 -3 +BITMAP +E0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +E0 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 9 0 0 +BITMAP +C0 +C0 +40 +60 +60 +20 +20 +30 +30 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 12 0 -3 +BITMAP +E0 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +E0 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 7 4 0 5 +BITMAP +10 +38 +6C +C6 +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 1 0 -3 +BITMAP +FE +ENDCHAR +STARTCHAR grave +ENCODING 96 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 0 8 +BITMAP +C0 +60 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 7 0 0 +BITMAP +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +C0 +C0 +D8 +EC +CC +CC +CC +EC +D8 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +C0 +C0 +C0 +CC +78 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +0C +0C +6C +DC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 9 0 0 +BITMAP +38 +60 +F0 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +6C +DC +CC +CC +CC +DC +6C +0C +CC +78 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +C0 +C0 +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 9 0 0 +BITMAP +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 12 -1 -3 +BITMAP +60 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +C0 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +C0 +C0 +CC +D8 +F0 +F0 +D8 +CC +C6 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 9 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 10 7 0 0 +BITMAP +BB80 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +D8 +EC +CC +CC +CC +EC +D8 +C0 +C0 +C0 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +74 +DC +CC +CC +CC +DC +6C +0C +0C +0C +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 5 7 0 0 +BITMAP +D8 +F8 +E0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +E0 +38 +1C +CC +78 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 9 0 0 +BITMAP +60 +60 +F0 +60 +60 +60 +60 +68 +30 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 7 0 0 +BITMAP +C6 +C6 +6C +6C +38 +38 +10 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 778 0 +DWIDTH 11 0 +BBX 10 7 0 0 +BITMAP +CCC0 +CCC0 +6D80 +6D80 +6D80 +3300 +3300 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +CC +CC +78 +30 +78 +CC +CC +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 10 0 -3 +BITMAP +C6 +C6 +6C +6C +38 +38 +18 +10 +30 +60 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 7 0 0 +BITMAP +F8 +18 +30 +20 +60 +C0 +F8 +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 4 12 0 -3 +BITMAP +30 +60 +60 +60 +60 +C0 +60 +60 +60 +60 +60 +30 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 280 0 +DWIDTH 4 0 +BBX 2 12 1 -3 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 4 12 0 -3 +BITMAP +C0 +60 +60 +60 +60 +30 +60 +60 +60 +60 +60 +C0 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 7 2 0 3 +BITMAP +76 +DC +ENDCHAR +STARTCHAR space +ENCODING 160 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclamdown +ENCODING 161 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 10 1 -3 +BITMAP +C0 +C0 +00 +40 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR cent +ENCODING 162 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 -1 +BITMAP +10 +78 +DC +90 +A0 +A0 +EC +78 +40 +ENDCHAR +STARTCHAR sterling +ENCODING 163 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +38 +6C +60 +60 +F8 +60 +60 +EC +D8 +ENDCHAR +STARTCHAR currency +ENCODING 164 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 6 0 1 +BITMAP +CC +78 +48 +48 +78 +CC +ENDCHAR +STARTCHAR yen +ENCODING 165 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +CC +CC +48 +FC +30 +FC +30 +30 +30 +ENDCHAR +STARTCHAR brokenbar +ENCODING 166 +SWIDTH 280 0 +DWIDTH 4 0 +BBX 2 11 1 -2 +BITMAP +C0 +C0 +C0 +C0 +00 +00 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR section +ENCODING 167 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 12 0 -3 +BITMAP +78 +CC +E0 +70 +D8 +CC +CC +6C +38 +1C +CC +78 +ENDCHAR +STARTCHAR dieresis +ENCODING 168 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 1 0 8 +BITMAP +D8 +ENDCHAR +STARTCHAR copyright +ENCODING 169 +SWIDTH 737 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +3E00 +4100 +9C80 +A280 +A080 +A280 +9C80 +4100 +3E00 +ENDCHAR +STARTCHAR ordfeminine +ENCODING 170 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 4 6 1 3 +BITMAP +E0 +30 +F0 +B0 +00 +F0 +ENDCHAR +STARTCHAR guillemotleft +ENCODING 171 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 6 5 1 1 +BITMAP +24 +6C +D8 +6C +24 +ENDCHAR +STARTCHAR logicalnot +ENCODING 172 +SWIDTH 584 0 +DWIDTH 8 0 +BBX 6 4 1 2 +BITMAP +FC +04 +04 +04 +ENDCHAR +STARTCHAR hyphen +ENCODING 173 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 0 3 +BITMAP +F0 +ENDCHAR +STARTCHAR registered +ENCODING 174 +SWIDTH 737 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +3E00 +4100 +9C80 +9480 +9880 +9480 +9480 +4100 +3E00 +ENDCHAR +STARTCHAR macron +ENCODING 175 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 1 0 8 +BITMAP +F0 +ENDCHAR +STARTCHAR degree +ENCODING 176 +SWIDTH 400 0 +DWIDTH 5 0 +BBX 4 4 0 4 +BITMAP +60 +90 +90 +60 +ENDCHAR +STARTCHAR plusminus +ENCODING 177 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +30 +30 +FC +30 +30 +00 +FC +ENDCHAR +STARTCHAR twosuperior +ENCODING 178 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 5 0 4 +BITMAP +60 +B0 +60 +C0 +F0 +ENDCHAR +STARTCHAR threesuperior +ENCODING 179 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 5 0 4 +BITMAP +60 +B0 +60 +30 +E0 +ENDCHAR +STARTCHAR acute +ENCODING 180 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 0 8 +BITMAP +60 +C0 +ENDCHAR +STARTCHAR mu +ENCODING 181 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +CC +CC +CC +CC +CC +DC +EC +C0 +C0 +C0 +ENDCHAR +STARTCHAR paragraph +ENCODING 182 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 12 0 -3 +BITMAP +3E +74 +F4 +F4 +F4 +74 +34 +14 +14 +14 +14 +14 +ENDCHAR +STARTCHAR periodcentered +ENCODING 183 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 2 1 3 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR cedilla +ENCODING 184 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 4 0 -3 +BITMAP +60 +30 +30 +E0 +ENDCHAR +STARTCHAR onesuperior +ENCODING 185 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 5 0 4 +BITMAP +60 +E0 +60 +60 +60 +ENDCHAR +STARTCHAR ordmasculine +ENCODING 186 +SWIDTH 365 0 +DWIDTH 6 0 +BBX 4 6 1 3 +BITMAP +60 +D0 +D0 +60 +00 +F0 +ENDCHAR +STARTCHAR guillemotright +ENCODING 187 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 6 5 1 1 +BITMAP +90 +D8 +6C +D8 +90 +ENDCHAR +STARTCHAR onequarter +ENCODING 188 +SWIDTH 834 0 +DWIDTH 10 0 +BBX 10 9 0 0 +BITMAP +6300 +E600 +6600 +6C00 +6D80 +0B80 +1A80 +37C0 +3180 +ENDCHAR +STARTCHAR onehalf +ENCODING 189 +SWIDTH 834 0 +DWIDTH 10 0 +BBX 10 9 0 0 +BITMAP +6300 +E600 +6600 +6C00 +6D80 +0AC0 +1980 +3300 +33C0 +ENDCHAR +STARTCHAR threequarters +ENCODING 190 +SWIDTH 834 0 +DWIDTH 10 0 +BBX 10 9 0 0 +BITMAP +6300 +B300 +6600 +3600 +ED80 +0B80 +1A80 +37C0 +3180 +ENDCHAR +STARTCHAR questiondown +ENCODING 191 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 6 10 1 -3 +BITMAP +30 +30 +00 +30 +30 +30 +60 +CC +CC +78 +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +30 +18 +00 +18 +18 +3C +24 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR Aacute +ENCODING 193 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +0C +18 +00 +18 +18 +3C +24 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR Acircumflex +ENCODING 194 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +1C +36 +00 +18 +18 +3C +24 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR Atilde +ENCODING 195 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +1A +2C +00 +18 +18 +3C +24 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR Adieresis +ENCODING 196 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 11 0 0 +BITMAP +36 +00 +18 +18 +3C +24 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR Aring +ENCODING 197 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +18 +24 +18 +18 +18 +3C +24 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR AE +ENCODING 198 +SWIDTH 1000 0 +DWIDTH 13 0 +BBX 11 9 1 0 +BITMAP +1FE0 +3600 +2600 +6600 +67E0 +7E00 +C600 +C600 +C7E0 +ENDCHAR +STARTCHAR Ccedilla +ENCODING 199 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 12 1 -3 +BITMAP +3C +66 +C0 +C0 +C0 +C0 +C0 +66 +3C +18 +18 +70 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +60 +30 +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR Eacute +ENCODING 201 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +18 +30 +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR Ecircumflex +ENCODING 202 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +38 +6C +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR Edieresis +ENCODING 203 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +6C +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR Igrave +ENCODING 204 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 3 12 0 0 +BITMAP +C0 +60 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR Iacute +ENCODING 205 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 3 12 1 0 +BITMAP +60 +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Icircumflex +ENCODING 206 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 5 12 0 0 +BITMAP +70 +D8 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR Idieresis +ENCODING 207 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 5 11 0 0 +BITMAP +D8 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR Eth +ENCODING 208 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 9 0 0 +BITMAP +7C +66 +63 +63 +F3 +63 +63 +66 +7C +ENDCHAR +STARTCHAR Ntilde +ENCODING 209 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +34 +58 +00 +C6 +C6 +E6 +E6 +F6 +CE +CE +C6 +C6 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +30 +18 +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR Oacute +ENCODING 211 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +0C +18 +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR Ocircumflex +ENCODING 212 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +1C +36 +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR Otilde +ENCODING 213 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +1A +2C +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR Odieresis +ENCODING 214 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +66 +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR multiply +ENCODING 215 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 5 0 1 +BITMAP +CC +78 +30 +78 +CC +ENDCHAR +STARTCHAR Oslash +ENCODING 216 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 10 1 -1 +BITMAP +3D +66 +CF +CB +DB +D3 +F3 +66 +7C +80 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +30 +18 +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR Uacute +ENCODING 218 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +0C +18 +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR Ucircumflex +ENCODING 219 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +38 +6C +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR Udieresis +ENCODING 220 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +6C +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR Yacute +ENCODING 221 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +0C +18 +00 +C3 +C3 +66 +66 +24 +3C +18 +18 +18 +ENDCHAR +STARTCHAR Thorn +ENCODING 222 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 9 1 0 +BITMAP +C0 +C0 +FC +C6 +C6 +C6 +FC +C0 +C0 +ENDCHAR +STARTCHAR germandbls +ENCODING 223 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +78 +CC +CC +CC +D8 +CC +CC +CC +D8 +ENDCHAR +STARTCHAR agrave +ENCODING 224 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +30 +18 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR aacute +ENCODING 225 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +18 +30 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR acircumflex +ENCODING 226 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +38 +6C +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR atilde +ENCODING 227 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +34 +58 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR adieresis +ENCODING 228 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +6C +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR aring +ENCODING 229 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 11 0 0 +BITMAP +30 +48 +30 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR ae +ENCODING 230 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 10 7 0 0 +BITMAP +7780 +CCC0 +0CC0 +7FC0 +CC00 +CCC0 +7780 +ENDCHAR +STARTCHAR ccedilla +ENCODING 231 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +78 +CC +C0 +C0 +C0 +CC +78 +10 +18 +70 +ENDCHAR +STARTCHAR egrave +ENCODING 232 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +60 +30 +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR eacute +ENCODING 233 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +18 +30 +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR ecircumflex +ENCODING 234 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +38 +6C +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR edieresis +ENCODING 235 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +6C +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR igrave +ENCODING 236 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 10 -1 0 +BITMAP +C0 +60 +00 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR iacute +ENCODING 237 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 10 0 0 +BITMAP +60 +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR icircumflex +ENCODING 238 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 10 -1 0 +BITMAP +70 +D8 +00 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR idieresis +ENCODING 239 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 9 -1 0 +BITMAP +D8 +00 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR eth +ENCODING 240 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +D8 +70 +90 +18 +7C +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR ntilde +ENCODING 241 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +34 +58 +00 +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR ograve +ENCODING 242 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +60 +30 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR oacute +ENCODING 243 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +18 +30 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR ocircumflex +ENCODING 244 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +38 +6C +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR otilde +ENCODING 245 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +34 +58 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR odieresis +ENCODING 246 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +6C +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR divide +ENCODING 247 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 5 0 1 +BITMAP +30 +00 +FC +00 +30 +ENDCHAR +STARTCHAR oslash +ENCODING 248 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 7 -1 0 +BITMAP +3D +66 +6E +76 +66 +66 +BC +ENDCHAR +STARTCHAR ugrave +ENCODING 249 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +60 +30 +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR uacute +ENCODING 250 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +18 +30 +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR ucircumflex +ENCODING 251 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +38 +6C +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR udieresis +ENCODING 252 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +6C +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR yacute +ENCODING 253 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 13 0 -3 +BITMAP +0C +18 +00 +C6 +C6 +6C +6C +38 +38 +18 +10 +30 +60 +ENDCHAR +STARTCHAR thorn +ENCODING 254 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 -3 +BITMAP +C0 +C0 +D8 +EC +CC +CC +CC +EC +D8 +C0 +C0 +C0 +ENDCHAR +STARTCHAR ydieresis +ENCODING 255 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 12 0 -3 +BITMAP +6C +00 +C6 +C6 +6C +6C +38 +38 +18 +10 +30 +60 +ENDCHAR +ENDFONT diff --git a/gui/themes/fonts/helvB12-iso-8859-5.bdf b/gui/themes/fonts/helvB12-iso-8859-5.bdf new file mode 100644 index 0000000000..dcfd6f0105 --- /dev/null +++ b/gui/themes/fonts/helvB12-iso-8859-5.bdf @@ -0,0 +1,2763 @@ +STARTFONT 2.1 +COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT! +COMMENT Generated with 'ucs2any helvB12c.bdf /usr/share/fonts/X11/util/map-ISO8859-5 ISO8859-5' +COMMENT from an ISO10646-1 encoded source BDF font. +COMMENT ucs2any by Ben Collver <collver1@attbi.com>, 2003, based on +COMMENT ucs2any.pl by Markus Kuhn <http://www.cl.cam.ac.uk/~mgk25/>, 2000. +FONT -Adobe-Helvetica-Bold-R-Normal--12-120-75-75-P-70-ISO8859-5 +SIZE 12 75 75 +FONTBOUNDINGBOX 13 15 -1 -3 +COMMENT $XConsortium: helvB12.bdf,v 1.13 95/01/26 18:01:34 gildea Exp $ +COMMENT +COMMENT + +COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated. +COMMENT Copyright 1988, 1994 Digital Equipment Corporation. +COMMENT +COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be +COMMENT registered in certain jurisdictions. +COMMENT Permission to use these trademarks is hereby granted only in +COMMENT association with the images described in this file. +COMMENT +COMMENT Permission to use, copy, modify, distribute and sell this software +COMMENT and its documentation for any purpose and without fee is hereby +COMMENT granted, provided that the above copyright notices appear in all +COMMENT copies and that both those copyright notices and this permission +COMMENT notice appear in supporting documentation, and that the names of +COMMENT Adobe Systems and Digital Equipment Corporation not be used in +COMMENT advertising or publicity pertaining to distribution of the software +COMMENT without specific, written prior permission. Adobe Systems and +COMMENT Digital Equipment Corporation make no representations about the +COMMENT suitability of this software for any purpose. It is provided "as +COMMENT is" without express or implied warranty. +COMMENT - +STARTPROPERTIES 32 +FOUNDRY "Adobe" +FAMILY_NAME "Helvetica" +WEIGHT_NAME "Bold" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 12 +POINT_SIZE 120 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "P" +AVERAGE_WIDTH 70 +CHARSET_REGISTRY "ISO8859" +CHARSET_ENCODING "5" +CAP_HEIGHT 9 +X_HEIGHT 7 +FONT_ASCENT 11 +FONT_DESCENT 3 +FACE_NAME "Helvetica Bold" +COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved." +NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. " +_DEC_DEVICE_FONTNAMES "PS=Helvetica-Bold" +_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991" +DEFAULT_CHAR 32 +RELATIVE_SETWIDTH 50 +RELATIVE_WEIGHT 70 +CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD" +FULL_NAME "Helvetica Bold" +COPYRIGHT2 "Cyrillic glyphs copyright 2000 Dmitry Yu. Bolkhovityanov, bolkhov@inp.nsk.su" +SOURCEDATE "Sun Jan 23 14:44:29 2000" +PKGVERSION "1.1" +ASSEMBLER "cvtbdf.pl (Linux)" +ENDPROPERTIES +CHARS 177 +STARTCHAR defaultchar +ENCODING 0 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 0 0 0 0 +BITMAP +ENDCHAR +STARTCHAR defaultchar +ENCODING 32 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 0 0 0 0 +BITMAP +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 9 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +80 +00 +C0 +C0 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 474 0 +DWIDTH 5 0 +BBX 3 3 1 6 +BITMAP +A0 +A0 +A0 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +14 +14 +7E +28 +28 +FC +50 +50 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 11 0 -2 +BITMAP +10 +78 +D4 +D0 +78 +1C +94 +D4 +78 +10 +10 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 889 0 +DWIDTH 12 0 +BBX 11 9 0 0 +BITMAP +7100 +DB00 +DA00 +7400 +0400 +09C0 +0B60 +1B60 +11C0 +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 9 0 0 +BITMAP +3800 +6C00 +6C00 +3800 +7900 +CF00 +C600 +CF00 +7980 +ENDCHAR +STARTCHAR quotesingle +ENCODING 39 +SWIDTH 238 0 +DWIDTH 3 0 +BBX 1 3 1 6 +BITMAP +80 +80 +80 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 4 12 1 -3 +BITMAP +30 +60 +60 +C0 +C0 +C0 +C0 +C0 +C0 +60 +60 +30 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 4 12 1 -3 +BITMAP +C0 +60 +60 +30 +30 +30 +30 +30 +30 +60 +60 +C0 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 389 0 +DWIDTH 6 0 +BBX 5 4 0 5 +BITMAP +20 +F8 +70 +50 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 5 0 1 +BITMAP +30 +30 +FC +30 +30 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 4 1 -2 +BITMAP +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR minus +ENCODING 45 +SWIDTH 584 0 +DWIDTH 8 0 +BBX 5 1 1 3 +BITMAP +F8 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 2 1 0 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 9 0 0 +BITMAP +30 +30 +20 +60 +60 +40 +40 +C0 +C0 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 4 9 0 0 +BITMAP +30 +F0 +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +0C +18 +30 +60 +C0 +C0 +FC +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +0C +38 +0C +0C +0C +CC +78 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +0C +1C +2C +2C +4C +8C +FE +0C +0C +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +7C +60 +C0 +F8 +0C +0C +CC +CC +78 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +C0 +C0 +F8 +CC +CC +CC +78 +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +FC +0C +18 +18 +30 +30 +30 +60 +60 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +CC +78 +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +CC +CC +7C +0C +0C +CC +78 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 7 1 0 +BITMAP +C0 +C0 +00 +00 +00 +C0 +C0 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 9 1 -2 +BITMAP +C0 +C0 +00 +00 +00 +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +18 +70 +C0 +70 +18 +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 3 0 2 +BITMAP +FC +00 +FC +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +C0 +70 +18 +70 +C0 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +78 +CC +CC +18 +30 +30 +00 +30 +30 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 975 0 +DWIDTH 12 0 +BBX 10 10 1 -1 +BITMAP +1F00 +6080 +4040 +8D40 +9240 +A240 +A680 +9B00 +4000 +3E00 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +18 +3C +24 +66 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +FC +C6 +C6 +C6 +FC +C6 +C6 +C6 +FC +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 9 1 0 +BITMAP +3C +66 +C0 +C0 +C0 +C0 +C0 +66 +3C +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +F8 +CC +C6 +C6 +C6 +C6 +C6 +CC +F8 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +3E +63 +C0 +C0 +CF +C3 +C3 +63 +3D +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +C6 +C6 +C6 +C6 +FE +C6 +C6 +C6 +C6 +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 9 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +0C +0C +0C +0C +0C +0C +CC +CC +78 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 9 1 0 +BITMAP +C6 +CC +D8 +F0 +F0 +D8 +CC +C6 +C3 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 833 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +C180 +C180 +E380 +E380 +F780 +D580 +DD80 +C980 +C980 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +C6 +E6 +E6 +D6 +D6 +CE +CE +C6 +C6 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 9 1 0 +BITMAP +FC +C6 +C6 +C6 +FC +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +3C +66 +C3 +C3 +C3 +CB +CF +66 +3F +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +FC +C6 +C6 +C6 +FC +CC +C6 +C6 +C6 +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +7C +C6 +C6 +70 +1C +0E +C6 +C6 +7C +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +FF +18 +18 +18 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +C3 +C3 +66 +66 +66 +24 +3C +18 +18 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 9 0 0 +BITMAP +CCC0 +CCC0 +CCC0 +4C80 +6D80 +6D80 +3300 +3300 +3300 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +C3 +C3 +66 +3C +18 +3C +66 +C3 +C3 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +C3 +C3 +66 +66 +3C +18 +18 +18 +18 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +FE +06 +0C +18 +30 +30 +60 +C0 +FE +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 12 1 -3 +BITMAP +E0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +E0 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 9 0 0 +BITMAP +C0 +C0 +40 +60 +60 +20 +20 +30 +30 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 12 0 -3 +BITMAP +E0 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +E0 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 7 4 0 5 +BITMAP +10 +38 +6C +C6 +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 1 0 -3 +BITMAP +FE +ENDCHAR +STARTCHAR grave +ENCODING 96 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 0 8 +BITMAP +C0 +60 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 7 0 0 +BITMAP +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +C0 +C0 +D8 +EC +CC +CC +CC +EC +D8 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +C0 +C0 +C0 +CC +78 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +0C +0C +6C +DC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 9 0 0 +BITMAP +38 +60 +F0 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +6C +DC +CC +CC +CC +DC +6C +0C +CC +78 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +C0 +C0 +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 9 0 0 +BITMAP +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 12 -1 -3 +BITMAP +60 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +C0 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +C0 +C0 +CC +D8 +F0 +F0 +D8 +CC +C6 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 9 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 10 7 0 0 +BITMAP +BB80 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +D8 +EC +CC +CC +CC +EC +D8 +C0 +C0 +C0 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +74 +DC +CC +CC +CC +DC +6C +0C +0C +0C +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 5 7 0 0 +BITMAP +D8 +F8 +E0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +E0 +38 +1C +CC +78 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 9 0 0 +BITMAP +60 +60 +F0 +60 +60 +60 +60 +68 +30 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 7 0 0 +BITMAP +C6 +C6 +6C +6C +38 +38 +10 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 778 0 +DWIDTH 11 0 +BBX 10 7 0 0 +BITMAP +CCC0 +CCC0 +6D80 +6D80 +6D80 +3300 +3300 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +CC +CC +78 +30 +78 +CC +CC +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 10 0 -3 +BITMAP +C6 +C6 +6C +6C +38 +38 +18 +10 +30 +60 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 7 0 0 +BITMAP +F8 +18 +30 +20 +60 +C0 +F8 +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 4 12 0 -3 +BITMAP +30 +60 +60 +60 +60 +C0 +60 +60 +60 +60 +60 +30 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 280 0 +DWIDTH 4 0 +BBX 2 12 1 -3 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 4 12 0 -3 +BITMAP +C0 +60 +60 +60 +60 +30 +60 +60 +60 +60 +60 +C0 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 7 2 0 3 +BITMAP +76 +DC +ENDCHAR +STARTCHAR space +ENCODING 160 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 0 0 0 0 +BITMAP +ENDCHAR +STARTCHAR afii10023 +ENCODING 161 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +6C +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR afii10053 +ENCODING 164 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 7 9 1 0 +BITMAP +3C +66 +C0 +C0 +F8 +C0 +C0 +66 +3C +ENDCHAR +STARTCHAR afii10054 +ENCODING 165 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +7C +C6 +C6 +70 +1C +0E +C6 +C6 +7C +ENDCHAR +STARTCHAR afii10055 +ENCODING 166 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 9 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR afii10056 +ENCODING 167 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 5 11 0 0 +BITMAP +D8 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR afii10057 +ENCODING 168 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +0C +0C +0C +0C +0C +0C +CC +CC +78 +ENDCHAR +STARTCHAR hyphen +ENCODING 173 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 0 3 +BITMAP +F0 +ENDCHAR +STARTCHAR afii10062 +ENCODING 174 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +66 +3C +00 +C3 +C3 +66 +66 +24 +3C +18 +18 +70 +ENDCHAR +STARTCHAR afii10017 +ENCODING 176 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +18 +3C +24 +66 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR afii10018 +ENCODING 177 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +FE +C0 +C0 +C0 +FC +C6 +C6 +C6 +FC +ENDCHAR +STARTCHAR afii10019 +ENCODING 178 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +FC +C6 +C6 +C6 +FC +C6 +C6 +C6 +FC +ENDCHAR +STARTCHAR afii10020 +ENCODING 179 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +FC +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR afii10021 +ENCODING 180 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 9 11 0 -2 +BITMAP +3F00 +3300 +3300 +3300 +3300 +3300 +6300 +6300 +FF80 +C180 +C180 +ENDCHAR +STARTCHAR afii10022 +ENCODING 181 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR afii10024 +ENCODING 182 +SWIDTH 960 0 +DWIDTH 12 0 +BBX 12 9 0 0 +BITMAP +C630 +6660 +36C0 +1F80 +0F00 +1F80 +36C0 +6660 +C630 +ENDCHAR +STARTCHAR afii10025 +ENCODING 183 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +7C +C6 +06 +06 +3C +06 +06 +C6 +7C +ENDCHAR +STARTCHAR afii10026 +ENCODING 184 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +C6 +C6 +CE +CE +D6 +D6 +E6 +E6 +C6 +ENDCHAR +STARTCHAR afii10027 +ENCODING 185 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +6C +38 +00 +C6 +C6 +CE +CE +D6 +D6 +E6 +E6 +C6 +ENDCHAR +STARTCHAR afii10028 +ENCODING 186 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 8 9 1 0 +BITMAP +C6 +CC +D8 +F0 +F0 +D8 +CC +C6 +C3 +ENDCHAR +STARTCHAR afii10029 +ENCODING 187 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 8 9 0 0 +BITMAP +3F +33 +33 +33 +33 +33 +33 +33 +E3 +ENDCHAR +STARTCHAR afii10030 +ENCODING 188 +SWIDTH 880 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +C180 +C180 +E380 +E380 +F780 +D580 +DD80 +C980 +C980 +ENDCHAR +STARTCHAR afii10031 +ENCODING 189 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +C6 +C6 +C6 +C6 +FE +C6 +C6 +C6 +C6 +ENDCHAR +STARTCHAR afii10032 +ENCODING 190 +SWIDTH 800 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR afii10033 +ENCODING 191 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +FE +C6 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +ENDCHAR +STARTCHAR afii10034 +ENCODING 192 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 7 9 1 0 +BITMAP +FC +C6 +C6 +C6 +FC +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR afii10035 +ENCODING 193 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 7 9 1 0 +BITMAP +3C +66 +C0 +C0 +C0 +C0 +C0 +66 +3C +ENDCHAR +STARTCHAR afii10036 +ENCODING 194 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +FF +18 +18 +18 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR afii10037 +ENCODING 195 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +C3 +C3 +66 +66 +24 +3C +18 +18 +70 +ENDCHAR +STARTCHAR afii10038 +ENCODING 196 +SWIDTH 960 0 +DWIDTH 12 0 +BBX 10 9 1 0 +BITMAP +0C00 +3F00 +6D80 +CCC0 +CCC0 +CCC0 +6D80 +3F00 +0C00 +ENDCHAR +STARTCHAR afii10039 +ENCODING 197 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +C3 +C3 +66 +3C +18 +3C +66 +C3 +C3 +ENDCHAR +STARTCHAR afii10040 +ENCODING 198 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 8 11 1 -2 +BITMAP +C6 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +FF +03 +03 +ENDCHAR +STARTCHAR afii10041 +ENCODING 199 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +C6 +C6 +C6 +C6 +7E +06 +06 +06 +06 +ENDCHAR +STARTCHAR afii10042 +ENCODING 200 +SWIDTH 960 0 +DWIDTH 12 0 +BBX 10 9 1 0 +BITMAP +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +FFC0 +ENDCHAR +STARTCHAR afii10043 +ENCODING 201 +SWIDTH 960 0 +DWIDTH 12 0 +BBX 11 11 1 -2 +BITMAP +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +FFE0 +0060 +0060 +ENDCHAR +STARTCHAR afii10044 +ENCODING 202 +SWIDTH 800 0 +DWIDTH 10 0 +BBX 9 9 0 0 +BITMAP +F000 +3000 +3000 +3000 +3F00 +3180 +3180 +3180 +3F00 +ENDCHAR +STARTCHAR afii10045 +ENCODING 203 +SWIDTH 1040 0 +DWIDTH 13 0 +BBX 11 9 1 0 +BITMAP +C060 +C060 +C060 +C060 +FC60 +C660 +C660 +C660 +FC60 +ENDCHAR +STARTCHAR afii10046 +ENCODING 204 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +C0 +C0 +C0 +C0 +FC +C6 +C6 +C6 +FC +ENDCHAR +STARTCHAR afii10047 +ENCODING 205 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +78 +CC +06 +06 +3E +06 +06 +CC +78 +ENDCHAR +STARTCHAR afii10048 +ENCODING 206 +SWIDTH 1040 0 +DWIDTH 13 0 +BBX 11 9 1 0 +BITMAP +C780 +CCC0 +D860 +D860 +F860 +D860 +D860 +CCC0 +C780 +ENDCHAR +STARTCHAR afii10049 +ENCODING 207 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +7E +C6 +C6 +C6 +7E +66 +66 +C6 +C6 +ENDCHAR +STARTCHAR afii10065 +ENCODING 208 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 7 7 0 0 +BITMAP +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR afii10066 +ENCODING 209 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +0C +78 +C0 +D8 +EC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR afii10067 +ENCODING 210 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +F8 +CC +CC +F8 +CC +CC +F8 +ENDCHAR +STARTCHAR afii10068 +ENCODING 211 +SWIDTH 400 0 +DWIDTH 5 0 +BBX 5 7 0 0 +BITMAP +F8 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR afii10069 +ENCODING 212 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 8 8 0 -1 +BITMAP +3E +36 +36 +36 +66 +66 +FF +C3 +ENDCHAR +STARTCHAR afii10070 +ENCODING 213 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR afii10072 +ENCODING 214 +SWIDTH 720 0 +DWIDTH 9 0 +BBX 8 7 0 0 +BITMAP +DB +DB +7E +3C +7E +DB +DB +ENDCHAR +STARTCHAR afii10073 +ENCODING 215 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +0C +38 +0C +CC +78 +ENDCHAR +STARTCHAR afii10074 +ENCODING 216 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +CC +CC +DC +FC +EC +CC +CC +ENDCHAR +STARTCHAR afii10075 +ENCODING 217 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +48 +78 +00 +CC +CC +DC +FC +EC +CC +CC +ENDCHAR +STARTCHAR afii10076 +ENCODING 218 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 7 7 0 0 +BITMAP +CC +D8 +F0 +F0 +D8 +CC +C6 +ENDCHAR +STARTCHAR afii10077 +ENCODING 219 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 8 7 -1 0 +BITMAP +3F +33 +33 +33 +33 +33 +E3 +ENDCHAR +STARTCHAR afii10078 +ENCODING 220 +SWIDTH 800 0 +DWIDTH 10 0 +BBX 9 7 0 0 +BITMAP +C180 +E380 +E380 +F780 +D580 +DD80 +C980 +ENDCHAR +STARTCHAR afii10079 +ENCODING 221 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +CC +CC +CC +FC +CC +CC +CC +ENDCHAR +STARTCHAR afii10080 +ENCODING 222 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR afii10081 +ENCODING 223 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +FC +CC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR afii10082 +ENCODING 224 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +D8 +EC +CC +CC +CC +EC +D8 +C0 +C0 +C0 +ENDCHAR +STARTCHAR afii10083 +ENCODING 225 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +C0 +C0 +C0 +CC +78 +ENDCHAR +STARTCHAR afii10084 +ENCODING 226 +SWIDTH 480 0 +DWIDTH 6 0 +BBX 6 7 0 0 +BITMAP +FC +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR afii10085 +ENCODING 227 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 7 10 0 -3 +BITMAP +C6 +C6 +6C +6C +38 +38 +18 +10 +30 +60 +ENDCHAR +STARTCHAR afii10086 +ENCODING 228 +SWIDTH 880 0 +DWIDTH 11 0 +BBX 10 12 0 -3 +BITMAP +0C00 +0C00 +7F80 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +7F80 +0C00 +0C00 +0C00 +ENDCHAR +STARTCHAR afii10087 +ENCODING 229 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +CC +CC +78 +30 +78 +CC +CC +ENDCHAR +STARTCHAR afii10088 +ENCODING 230 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 7 8 0 -1 +BITMAP +CC +CC +CC +CC +CC +CC +FE +06 +ENDCHAR +STARTCHAR afii10089 +ENCODING 231 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +CC +CC +CC +7C +0C +0C +0C +ENDCHAR +STARTCHAR afii10090 +ENCODING 232 +SWIDTH 880 0 +DWIDTH 11 0 +BBX 10 7 0 0 +BITMAP +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +FFC0 +ENDCHAR +STARTCHAR afii10091 +ENCODING 233 +SWIDTH 880 0 +DWIDTH 11 0 +BBX 11 8 0 -1 +BITMAP +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +FFE0 +0060 +ENDCHAR +STARTCHAR afii10092 +ENCODING 234 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 8 7 -1 0 +BITMAP +F0 +30 +30 +3E +33 +33 +3E +ENDCHAR +STARTCHAR afii10093 +ENCODING 235 +SWIDTH 800 0 +DWIDTH 10 0 +BBX 9 7 0 0 +BITMAP +C180 +C180 +C180 +F980 +CD80 +CD80 +F980 +ENDCHAR +STARTCHAR afii10094 +ENCODING 236 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +C0 +C0 +C0 +F8 +CC +CC +F8 +ENDCHAR +STARTCHAR afii10095 +ENCODING 237 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +0C +3C +0C +CC +78 +ENDCHAR +STARTCHAR afii10096 +ENCODING 238 +SWIDTH 880 0 +DWIDTH 11 0 +BBX 10 7 0 0 +BITMAP +C780 +CCC0 +CCC0 +FCC0 +CCC0 +CCC0 +C780 +ENDCHAR +STARTCHAR afii10097 +ENCODING 239 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +7C +CC +CC +7C +6C +CC +CC +ENDCHAR +STARTCHAR afii10071 +ENCODING 241 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +6C +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR afii10101 +ENCODING 244 +SWIDTH 560 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +C0 +F0 +C0 +CC +78 +ENDCHAR +STARTCHAR afii10102 +ENCODING 245 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +E0 +38 +1C +CC +78 +ENDCHAR +STARTCHAR afii10103 +ENCODING 246 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 9 0 0 +BITMAP +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR afii10104 +ENCODING 247 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 9 -1 0 +BITMAP +D8 +00 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR afii10105 +ENCODING 248 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 12 -1 -3 +BITMAP +60 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +C0 +ENDCHAR +STARTCHAR section +ENCODING 253 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 12 0 -3 +BITMAP +78 +CC +E0 +70 +D8 +CC +CC +6C +38 +1C +CC +78 +ENDCHAR +STARTCHAR afii10110 +ENCODING 254 +SWIDTH 640 0 +DWIDTH 8 0 +BBX 7 13 0 -3 +BITMAP +44 +38 +00 +C6 +C6 +6C +6C +38 +38 +18 +10 +30 +60 +ENDCHAR +ENDFONT diff --git a/gui/themes/fonts/helvB12.bdf b/gui/themes/fonts/helvB12.bdf new file mode 100644 index 0000000000..76f5dbc552 --- /dev/null +++ b/gui/themes/fonts/helvB12.bdf @@ -0,0 +1,12708 @@ +STARTFONT 2.1 +FONT -Adobe-Helvetica-Bold-R-Normal--12-120-75-75-P-70-ISO10646-1 +SIZE 12 75 75 +FONTBOUNDINGBOX 15 20 -2 -5 +COMMENT $Xorg: $ +COMMENT ISO10646-1 extension by Markus Kuhn <mkuhn@acm.org>, 2001-03-20 +COMMENT +COMMENT + +COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated. +COMMENT Copyright 1988, 1994 Digital Equipment Corporation. +COMMENT +COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be +COMMENT registered in certain jurisdictions. +COMMENT Permission to use these trademarks is hereby granted only in +COMMENT association with the images described in this file. +COMMENT +COMMENT Permission to use, copy, modify, distribute and sell this software +COMMENT and its documentation for any purpose and without fee is hereby +COMMENT granted, provided that the above copyright notices appear in all +COMMENT copies and that both those copyright notices and this permission +COMMENT notice appear in supporting documentation, and that the names of +COMMENT Adobe Systems and Digital Equipment Corporation not be used in +COMMENT advertising or publicity pertaining to distribution of the software +COMMENT without specific, written prior permission. Adobe Systems and +COMMENT Digital Equipment Corporation make no representations about the +COMMENT suitability of this software for any purpose. It is provided "as +COMMENT is" without express or implied warranty. +COMMENT - +STARTPROPERTIES 26 +FOUNDRY "Adobe" +FAMILY_NAME "Helvetica" +WEIGHT_NAME "Bold" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 12 +POINT_SIZE 120 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "P" +AVERAGE_WIDTH 70 +CHARSET_REGISTRY "ISO10646" +CHARSET_ENCODING "1" +CAP_HEIGHT 9 +X_HEIGHT 7 +FONT_ASCENT 11 +FONT_DESCENT 3 +FACE_NAME "Helvetica Bold" +COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved." +NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. " +_DEC_DEVICE_FONTNAMES "PS=Helvetica-Bold" +DEFAULT_CHAR 0 +RELATIVE_SETWIDTH 50 +RELATIVE_WEIGHT 70 +FULL_NAME "Helvetica Bold" +ENDPROPERTIES +CHARS 756 +STARTCHAR char0 +ENCODING 0 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +AA +00 +82 +00 +82 +00 +82 +00 +AA +ENDCHAR +STARTCHAR space +ENCODING 32 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 9 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +80 +00 +C0 +C0 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 474 0 +DWIDTH 5 0 +BBX 3 3 1 6 +BITMAP +A0 +A0 +A0 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 8 0 0 +BITMAP +14 +14 +7E +28 +28 +FC +50 +50 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 11 0 -2 +BITMAP +10 +78 +D4 +D0 +78 +1C +94 +D4 +78 +10 +10 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 889 0 +DWIDTH 12 0 +BBX 11 9 0 0 +BITMAP +7100 +DB00 +DA00 +7400 +0400 +09C0 +0B60 +1B60 +11C0 +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 9 0 0 +BITMAP +3800 +6C00 +6C00 +3800 +7900 +CF00 +C600 +CF00 +7980 +ENDCHAR +STARTCHAR quotesingle +ENCODING 39 +SWIDTH 238 0 +DWIDTH 3 0 +BBX 1 3 1 6 +BITMAP +80 +80 +80 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 4 12 1 -3 +BITMAP +30 +60 +60 +C0 +C0 +C0 +C0 +C0 +C0 +60 +60 +30 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 4 12 1 -3 +BITMAP +C0 +60 +60 +30 +30 +30 +30 +30 +30 +60 +60 +C0 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 389 0 +DWIDTH 6 0 +BBX 5 4 0 5 +BITMAP +20 +F8 +70 +50 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 5 0 1 +BITMAP +30 +30 +FC +30 +30 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 4 1 -2 +BITMAP +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR hyphen +ENCODING 45 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 0 3 +BITMAP +F0 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 2 1 0 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 9 0 0 +BITMAP +30 +30 +20 +60 +60 +40 +40 +C0 +C0 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +CC +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 4 9 0 0 +BITMAP +30 +F0 +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +0C +18 +30 +60 +C0 +C0 +FC +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +0C +38 +0C +0C +0C +CC +78 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +0C +1C +2C +2C +4C +8C +FE +0C +0C +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +7C +60 +C0 +F8 +0C +0C +CC +CC +78 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +C0 +C0 +F8 +CC +CC +CC +78 +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +FC +0C +18 +18 +30 +30 +30 +60 +60 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +CC +78 +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +CC +CC +7C +0C +0C +CC +78 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 7 1 0 +BITMAP +C0 +C0 +00 +00 +00 +C0 +C0 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 9 1 -2 +BITMAP +C0 +C0 +00 +00 +00 +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +18 +70 +C0 +70 +18 +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 3 0 2 +BITMAP +FC +00 +FC +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +C0 +70 +18 +70 +C0 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +78 +CC +CC +18 +30 +30 +00 +30 +30 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 975 0 +DWIDTH 12 0 +BBX 10 10 1 -1 +BITMAP +1F00 +6080 +4040 +8D40 +9240 +A240 +A680 +9B00 +4000 +3E00 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +18 +3C +24 +66 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +FC +C6 +C6 +C6 +FC +C6 +C6 +C6 +FC +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 9 1 0 +BITMAP +3C +66 +C0 +C0 +C0 +C0 +C0 +66 +3C +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +F8 +CC +C6 +C6 +C6 +C6 +C6 +CC +F8 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +3E +63 +C0 +C0 +CF +C3 +C3 +63 +3D +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +C6 +C6 +C6 +C6 +FE +C6 +C6 +C6 +C6 +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 9 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +0C +0C +0C +0C +0C +0C +CC +CC +78 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 9 1 0 +BITMAP +C6 +CC +D8 +F0 +F0 +D8 +CC +C6 +C3 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 833 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +C180 +C180 +E380 +E380 +F780 +D580 +DD80 +C980 +C980 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +C6 +E6 +E6 +D6 +D6 +CE +CE +C6 +C6 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 9 1 0 +BITMAP +FC +C6 +C6 +C6 +FC +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +3C +66 +C3 +C3 +C3 +CB +CF +66 +3F +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +FC +C6 +C6 +C6 +FC +CC +C6 +C6 +C6 +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +7C +C6 +C6 +70 +1C +0E +C6 +C6 +7C +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +FF +18 +18 +18 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +C3 +C3 +66 +66 +66 +24 +3C +18 +18 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 9 0 0 +BITMAP +CCC0 +CCC0 +CCC0 +4C80 +6D80 +6D80 +3300 +3300 +3300 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +C3 +C3 +66 +3C +18 +3C +66 +C3 +C3 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +C3 +C3 +66 +66 +3C +18 +18 +18 +18 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +FE +06 +0C +18 +30 +30 +60 +C0 +FE +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 12 1 -3 +BITMAP +E0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +E0 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 9 0 0 +BITMAP +C0 +C0 +40 +60 +60 +20 +20 +30 +30 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 12 0 -3 +BITMAP +E0 +60 +60 +60 +60 +60 +60 +60 +60 +60 +60 +E0 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 7 4 0 5 +BITMAP +10 +38 +6C +C6 +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 1 0 -3 +BITMAP +FE +ENDCHAR +STARTCHAR grave +ENCODING 96 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 0 8 +BITMAP +C0 +60 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 7 0 0 +BITMAP +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +C0 +C0 +D8 +EC +CC +CC +CC +EC +D8 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +C0 +C0 +C0 +CC +78 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +0C +0C +6C +DC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 9 0 0 +BITMAP +38 +60 +F0 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +6C +DC +CC +CC +CC +DC +6C +0C +CC +78 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +C0 +C0 +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 9 0 0 +BITMAP +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 12 -1 -3 +BITMAP +60 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +C0 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +C0 +C0 +CC +D8 +F0 +F0 +D8 +CC +C6 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 9 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 10 7 0 0 +BITMAP +BB80 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +D8 +EC +CC +CC +CC +EC +D8 +C0 +C0 +C0 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +74 +DC +CC +CC +CC +DC +6C +0C +0C +0C +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 5 7 0 0 +BITMAP +D8 +F8 +E0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +E0 +38 +1C +CC +78 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 9 0 0 +BITMAP +60 +60 +F0 +60 +60 +60 +60 +68 +30 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 7 0 0 +BITMAP +C6 +C6 +6C +6C +38 +38 +10 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 778 0 +DWIDTH 11 0 +BBX 10 7 0 0 +BITMAP +CCC0 +CCC0 +6D80 +6D80 +6D80 +3300 +3300 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +CC +CC +78 +30 +78 +CC +CC +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 10 0 -3 +BITMAP +C6 +C6 +6C +6C +38 +38 +18 +10 +30 +60 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 7 0 0 +BITMAP +F8 +18 +30 +20 +60 +C0 +F8 +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 4 12 0 -3 +BITMAP +30 +60 +60 +60 +60 +C0 +60 +60 +60 +60 +60 +30 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 280 0 +DWIDTH 4 0 +BBX 2 12 1 -3 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 4 12 0 -3 +BITMAP +C0 +60 +60 +60 +60 +30 +60 +60 +60 +60 +60 +C0 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 7 2 0 3 +BITMAP +76 +DC +ENDCHAR +STARTCHAR space +ENCODING 160 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclamdown +ENCODING 161 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 10 1 -3 +BITMAP +C0 +C0 +00 +40 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR cent +ENCODING 162 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 -1 +BITMAP +10 +78 +DC +90 +A0 +A0 +EC +78 +40 +ENDCHAR +STARTCHAR sterling +ENCODING 163 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +38 +6C +60 +60 +F8 +60 +60 +EC +D8 +ENDCHAR +STARTCHAR currency +ENCODING 164 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 6 0 1 +BITMAP +CC +78 +48 +48 +78 +CC +ENDCHAR +STARTCHAR yen +ENCODING 165 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +CC +CC +48 +FC +30 +FC +30 +30 +30 +ENDCHAR +STARTCHAR brokenbar +ENCODING 166 +SWIDTH 280 0 +DWIDTH 4 0 +BBX 2 11 1 -2 +BITMAP +C0 +C0 +C0 +C0 +00 +00 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR section +ENCODING 167 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 12 0 -3 +BITMAP +78 +CC +E0 +70 +D8 +CC +CC +6C +38 +1C +CC +78 +ENDCHAR +STARTCHAR dieresis +ENCODING 168 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 1 0 8 +BITMAP +D8 +ENDCHAR +STARTCHAR copyright +ENCODING 169 +SWIDTH 737 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +3E00 +4100 +9C80 +A280 +A080 +A280 +9C80 +4100 +3E00 +ENDCHAR +STARTCHAR ordfeminine +ENCODING 170 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 4 6 1 3 +BITMAP +E0 +30 +F0 +B0 +00 +F0 +ENDCHAR +STARTCHAR guillemotleft +ENCODING 171 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 6 5 1 1 +BITMAP +24 +6C +D8 +6C +24 +ENDCHAR +STARTCHAR logicalnot +ENCODING 172 +SWIDTH 584 0 +DWIDTH 8 0 +BBX 6 4 1 2 +BITMAP +FC +04 +04 +04 +ENDCHAR +STARTCHAR hyphen +ENCODING 173 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 0 3 +BITMAP +F0 +ENDCHAR +STARTCHAR registered +ENCODING 174 +SWIDTH 737 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +3E00 +4100 +9C80 +9480 +9880 +9480 +9480 +4100 +3E00 +ENDCHAR +STARTCHAR macron +ENCODING 175 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 1 0 8 +BITMAP +F0 +ENDCHAR +STARTCHAR degree +ENCODING 176 +SWIDTH 400 0 +DWIDTH 5 0 +BBX 4 4 0 4 +BITMAP +60 +90 +90 +60 +ENDCHAR +STARTCHAR plusminus +ENCODING 177 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +30 +30 +FC +30 +30 +00 +FC +ENDCHAR +STARTCHAR twosuperior +ENCODING 178 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 5 0 4 +BITMAP +60 +B0 +60 +C0 +F0 +ENDCHAR +STARTCHAR threesuperior +ENCODING 179 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 5 0 4 +BITMAP +60 +B0 +60 +30 +E0 +ENDCHAR +STARTCHAR acute +ENCODING 180 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 0 8 +BITMAP +60 +C0 +ENDCHAR +STARTCHAR mu +ENCODING 181 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +CC +CC +CC +CC +CC +DC +EC +C0 +C0 +C0 +ENDCHAR +STARTCHAR paragraph +ENCODING 182 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 12 0 -3 +BITMAP +3E +74 +F4 +F4 +F4 +74 +34 +14 +14 +14 +14 +14 +ENDCHAR +STARTCHAR periodcentered +ENCODING 183 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 2 1 3 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR cedilla +ENCODING 184 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 4 0 -3 +BITMAP +60 +30 +30 +E0 +ENDCHAR +STARTCHAR onesuperior +ENCODING 185 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 5 0 4 +BITMAP +60 +E0 +60 +60 +60 +ENDCHAR +STARTCHAR ordmasculine +ENCODING 186 +SWIDTH 365 0 +DWIDTH 6 0 +BBX 4 6 1 3 +BITMAP +60 +D0 +D0 +60 +00 +F0 +ENDCHAR +STARTCHAR guillemotright +ENCODING 187 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 6 5 1 1 +BITMAP +90 +D8 +6C +D8 +90 +ENDCHAR +STARTCHAR onequarter +ENCODING 188 +SWIDTH 834 0 +DWIDTH 10 0 +BBX 10 9 0 0 +BITMAP +6300 +E600 +6600 +6C00 +6D80 +0B80 +1A80 +37C0 +3180 +ENDCHAR +STARTCHAR onehalf +ENCODING 189 +SWIDTH 834 0 +DWIDTH 10 0 +BBX 10 9 0 0 +BITMAP +6300 +E600 +6600 +6C00 +6D80 +0AC0 +1980 +3300 +33C0 +ENDCHAR +STARTCHAR threequarters +ENCODING 190 +SWIDTH 834 0 +DWIDTH 10 0 +BBX 10 9 0 0 +BITMAP +6300 +B300 +6600 +3600 +ED80 +0B80 +1A80 +37C0 +3180 +ENDCHAR +STARTCHAR questiondown +ENCODING 191 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 6 10 1 -3 +BITMAP +30 +30 +00 +30 +30 +30 +60 +CC +CC +78 +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +30 +18 +00 +18 +18 +3C +24 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR Aacute +ENCODING 193 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +0C +18 +00 +18 +18 +3C +24 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR Acircumflex +ENCODING 194 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +1C +36 +00 +18 +18 +3C +24 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR Atilde +ENCODING 195 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +1A +2C +00 +18 +18 +3C +24 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR Adieresis +ENCODING 196 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 11 0 0 +BITMAP +36 +00 +18 +18 +3C +24 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR Aring +ENCODING 197 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +18 +24 +18 +18 +18 +3C +24 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR AE +ENCODING 198 +SWIDTH 1000 0 +DWIDTH 13 0 +BBX 11 9 1 0 +BITMAP +1FE0 +3600 +2600 +6600 +67E0 +7E00 +C600 +C600 +C7E0 +ENDCHAR +STARTCHAR Ccedilla +ENCODING 199 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 12 1 -3 +BITMAP +3C +66 +C0 +C0 +C0 +C0 +C0 +66 +3C +18 +18 +70 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +60 +30 +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR Eacute +ENCODING 201 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +18 +30 +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR Ecircumflex +ENCODING 202 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +38 +6C +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR Edieresis +ENCODING 203 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +6C +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR Igrave +ENCODING 204 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 3 12 0 0 +BITMAP +C0 +60 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR Iacute +ENCODING 205 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 3 12 1 0 +BITMAP +60 +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Icircumflex +ENCODING 206 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 5 12 0 0 +BITMAP +70 +D8 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR Idieresis +ENCODING 207 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 5 11 0 0 +BITMAP +D8 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR Eth +ENCODING 208 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 9 0 0 +BITMAP +7C +66 +63 +63 +F3 +63 +63 +66 +7C +ENDCHAR +STARTCHAR Ntilde +ENCODING 209 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +34 +58 +00 +C6 +C6 +E6 +E6 +F6 +CE +CE +C6 +C6 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +30 +18 +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR Oacute +ENCODING 211 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +0C +18 +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR Ocircumflex +ENCODING 212 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +1C +36 +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR Otilde +ENCODING 213 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +1A +2C +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR Odieresis +ENCODING 214 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +66 +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR multiply +ENCODING 215 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 5 0 1 +BITMAP +CC +78 +30 +78 +CC +ENDCHAR +STARTCHAR Oslash +ENCODING 216 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 10 1 -1 +BITMAP +3D +66 +CF +CB +DB +D3 +F3 +66 +7C +80 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +30 +18 +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR Uacute +ENCODING 218 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +0C +18 +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR Ucircumflex +ENCODING 219 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +38 +6C +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR Udieresis +ENCODING 220 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +6C +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR Yacute +ENCODING 221 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +0C +18 +00 +C3 +C3 +66 +66 +24 +3C +18 +18 +18 +ENDCHAR +STARTCHAR Thorn +ENCODING 222 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 9 1 0 +BITMAP +C0 +C0 +FC +C6 +C6 +C6 +FC +C0 +C0 +ENDCHAR +STARTCHAR germandbls +ENCODING 223 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +78 +CC +CC +CC +D8 +CC +CC +CC +D8 +ENDCHAR +STARTCHAR agrave +ENCODING 224 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +30 +18 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR aacute +ENCODING 225 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +18 +30 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR acircumflex +ENCODING 226 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +38 +6C +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR atilde +ENCODING 227 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +34 +58 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR adieresis +ENCODING 228 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +6C +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR aring +ENCODING 229 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 11 0 0 +BITMAP +30 +48 +30 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR ae +ENCODING 230 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 10 7 0 0 +BITMAP +7780 +CCC0 +0CC0 +7FC0 +CC00 +CCC0 +7780 +ENDCHAR +STARTCHAR ccedilla +ENCODING 231 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +78 +CC +C0 +C0 +C0 +CC +78 +10 +18 +70 +ENDCHAR +STARTCHAR egrave +ENCODING 232 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +60 +30 +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR eacute +ENCODING 233 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +18 +30 +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR ecircumflex +ENCODING 234 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +38 +6C +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR edieresis +ENCODING 235 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +6C +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR igrave +ENCODING 236 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 10 -1 0 +BITMAP +C0 +60 +00 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR iacute +ENCODING 237 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 10 0 0 +BITMAP +60 +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR icircumflex +ENCODING 238 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 10 -1 0 +BITMAP +70 +D8 +00 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR idieresis +ENCODING 239 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 9 -1 0 +BITMAP +D8 +00 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR eth +ENCODING 240 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +D8 +70 +90 +18 +7C +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR ntilde +ENCODING 241 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +34 +58 +00 +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR ograve +ENCODING 242 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +60 +30 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR oacute +ENCODING 243 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +18 +30 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR ocircumflex +ENCODING 244 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +38 +6C +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR otilde +ENCODING 245 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +34 +58 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR odieresis +ENCODING 246 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +6C +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR divide +ENCODING 247 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 5 0 1 +BITMAP +30 +00 +FC +00 +30 +ENDCHAR +STARTCHAR oslash +ENCODING 248 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 7 -1 0 +BITMAP +3D +66 +6E +76 +66 +66 +BC +ENDCHAR +STARTCHAR ugrave +ENCODING 249 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +60 +30 +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR uacute +ENCODING 250 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +18 +30 +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR ucircumflex +ENCODING 251 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +38 +6C +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR udieresis +ENCODING 252 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +6C +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR yacute +ENCODING 253 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 13 0 -3 +BITMAP +0C +18 +00 +C6 +C6 +6C +6C +38 +38 +18 +10 +30 +60 +ENDCHAR +STARTCHAR thorn +ENCODING 254 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 -3 +BITMAP +C0 +C0 +D8 +EC +CC +CC +CC +EC +D8 +C0 +C0 +C0 +ENDCHAR +STARTCHAR ydieresis +ENCODING 255 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 12 0 -3 +BITMAP +6C +00 +C6 +C6 +6C +6C +38 +38 +18 +10 +30 +60 +ENDCHAR +STARTCHAR Amacron +ENCODING 256 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 11 0 0 +BITMAP +3C +00 +18 +3C +24 +66 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR amacron +ENCODING 257 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +78 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR Abreve +ENCODING 258 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +22 +1C +00 +18 +3C +24 +66 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR abreve +ENCODING 259 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +44 +38 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR Aogonek +ENCODING 260 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 -3 +BITMAP +18 +3C +24 +66 +66 +7E +C3 +C3 +DB +30 +30 +1C +ENDCHAR +STARTCHAR aogonek +ENCODING 261 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 0 -3 +BITMAP +78 +CC +0C +7C +CC +CC +7E +30 +30 +1C +ENDCHAR +STARTCHAR Cacute +ENCODING 262 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 12 1 0 +BITMAP +18 +30 +00 +3C +66 +C0 +C0 +C0 +C0 +C0 +66 +3C +ENDCHAR +STARTCHAR cacute +ENCODING 263 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +18 +30 +00 +78 +CC +C0 +C0 +C0 +CC +78 +ENDCHAR +STARTCHAR Ccircumflex +ENCODING 264 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 12 1 0 +BITMAP +38 +6C +00 +3C +66 +C0 +C0 +C0 +C0 +C0 +66 +3C +ENDCHAR +STARTCHAR ccircumflex +ENCODING 265 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +38 +6C +00 +78 +CC +C0 +C0 +C0 +CC +78 +ENDCHAR +STARTCHAR Cdotaccent +ENCODING 266 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 11 1 0 +BITMAP +30 +00 +3C +66 +C0 +C0 +C0 +C0 +C0 +66 +3C +ENDCHAR +STARTCHAR cdotaccent +ENCODING 267 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +30 +00 +78 +CC +C0 +C0 +C0 +CC +78 +ENDCHAR +STARTCHAR Ccaron +ENCODING 268 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 12 1 0 +BITMAP +6C +38 +00 +3C +66 +C0 +C0 +C0 +C0 +C0 +66 +3C +ENDCHAR +STARTCHAR ccaron +ENCODING 269 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +6C +38 +00 +78 +CC +C0 +C0 +C0 +CC +78 +ENDCHAR +STARTCHAR Dcaron +ENCODING 270 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +6C +38 +00 +F8 +CC +C6 +C6 +C6 +C6 +C6 +CC +F8 +ENDCHAR +STARTCHAR dcaron +ENCODING 271 +SWIDTH 858 0 +DWIDTH 11 0 +BBX 10 9 0 0 +BITMAP +0CC0 +0C40 +6C80 +DC00 +CC00 +CC00 +CC00 +DC00 +6C00 +ENDCHAR +STARTCHAR Dcroat +ENCODING 272 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 9 0 0 +BITMAP +7C +66 +63 +63 +F3 +63 +63 +66 +7C +ENDCHAR +STARTCHAR dcroat +ENCODING 273 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +0C +3E +6C +DC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR Emacron +ENCODING 274 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +F0 +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR emacron +ENCODING 275 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR Ebreve +ENCODING 276 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +88 +70 +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR ebreve +ENCODING 277 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +44 +38 +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR Edotaccent +ENCODING 278 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +60 +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR edotaccent +ENCODING 279 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +30 +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR Eogonek +ENCODING 280 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 -3 +BITMAP +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +60 +60 +38 +ENDCHAR +STARTCHAR eogonek +ENCODING 281 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +78 +CC +CC +FC +C0 +CC +78 +60 +60 +38 +ENDCHAR +STARTCHAR Ecaron +ENCODING 282 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +D8 +70 +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR ecaron +ENCODING 283 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +6C +38 +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR Gcircumflex +ENCODING 284 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +38 +6C +00 +3E +63 +C0 +C0 +CF +C3 +C3 +63 +3D +ENDCHAR +STARTCHAR gcircumflex +ENCODING 285 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 13 0 -3 +BITMAP +38 +6C +00 +6C +DC +CC +CC +CC +DC +6C +0C +CC +78 +ENDCHAR +STARTCHAR Gbreve +ENCODING 286 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +44 +38 +00 +3E +63 +C0 +C0 +CF +C3 +C3 +63 +3D +ENDCHAR +STARTCHAR gbreve +ENCODING 287 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 13 0 -3 +BITMAP +44 +38 +00 +6C +DC +CC +CC +CC +DC +6C +0C +CC +78 +ENDCHAR +STARTCHAR Gdotaccent +ENCODING 288 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +18 +00 +3E +63 +C0 +C0 +CF +C3 +C3 +63 +3D +ENDCHAR +STARTCHAR gdotaccent +ENCODING 289 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 -3 +BITMAP +30 +00 +6C +DC +CC +CC +CC +DC +6C +0C +CC +78 +ENDCHAR +STARTCHAR Gcommaaccent +ENCODING 290 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 14 1 -5 +BITMAP +3E +63 +C0 +C0 +CF +C3 +C3 +63 +3D +00 +18 +18 +08 +10 +ENDCHAR +STARTCHAR gcommaaccent +ENCODING 291 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 14 0 -3 +BITMAP +10 +20 +30 +00 +6C +DC +CC +CC +CC +DC +6C +0C +CC +78 +ENDCHAR +STARTCHAR Hcircumflex +ENCODING 292 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +38 +6C +00 +C6 +C6 +C6 +C6 +FE +C6 +C6 +C6 +C6 +ENDCHAR +STARTCHAR hcircumflex +ENCODING 293 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 0 +BITMAP +70 +D8 +00 +C0 +C0 +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR Hbar +ENCODING 294 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +C6 +FE +C6 +C6 +FE +C6 +C6 +C6 +C6 +ENDCHAR +STARTCHAR hbar +ENCODING 295 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +C0 +F8 +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR Itilde +ENCODING 296 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 5 12 0 0 +BITMAP +68 +B0 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR itilde +ENCODING 297 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 10 -1 0 +BITMAP +68 +B0 +00 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR Imacron +ENCODING 298 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 11 0 0 +BITMAP +F0 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR imacron +ENCODING 299 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 9 -1 0 +BITMAP +F0 +00 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR Ibreve +ENCODING 300 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 5 12 0 0 +BITMAP +88 +70 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR ibreve +ENCODING 301 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 10 -1 0 +BITMAP +88 +70 +00 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR Iogonek +ENCODING 302 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 12 0 -3 +BITMAP +60 +60 +60 +60 +60 +60 +60 +60 +60 +C0 +C0 +70 +ENDCHAR +STARTCHAR iogonek +ENCODING 303 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 12 -1 -3 +BITMAP +60 +00 +60 +60 +60 +60 +60 +60 +60 +C0 +C0 +70 +ENDCHAR +STARTCHAR Idotaccent +ENCODING 304 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 11 1 0 +BITMAP +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR dotlessi +ENCODING 305 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 7 0 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR IJ +ENCODING 306 +SWIDTH 820 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +C180 +C180 +C180 +C180 +C180 +C180 +D980 +D980 +CF00 +ENDCHAR +STARTCHAR ij +ENCODING 307 +SWIDTH 542 0 +DWIDTH 6 0 +BBX 5 12 0 -3 +BITMAP +D8 +00 +D8 +D8 +D8 +D8 +D8 +D8 +D8 +18 +18 +30 +ENDCHAR +STARTCHAR Jcircumflex +ENCODING 308 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 12 0 0 +BITMAP +1C +36 +00 +0C +0C +0C +0C +0C +0C +CC +CC +78 +ENDCHAR +STARTCHAR jcircumflex +ENCODING 309 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 13 -2 -3 +BITMAP +70 +D8 +00 +30 +30 +30 +30 +30 +30 +30 +30 +30 +60 +ENDCHAR +STARTCHAR Kcommaaccent +ENCODING 310 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 14 1 -5 +BITMAP +C6 +CC +D8 +F0 +F0 +D8 +CC +C6 +C3 +00 +18 +18 +08 +10 +ENDCHAR +STARTCHAR kcommaaccent +ENCODING 311 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 14 0 -5 +BITMAP +C0 +C0 +CC +D8 +F0 +F0 +D8 +CC +C6 +00 +30 +30 +10 +20 +ENDCHAR +STARTCHAR kgreenlandic +ENCODING 312 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 7 0 0 +BITMAP +CC +D8 +F0 +F0 +D8 +CC +C6 +ENDCHAR +STARTCHAR Lacute +ENCODING 313 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 1 0 +BITMAP +30 +60 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR lacute +ENCODING 314 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 12 0 0 +BITMAP +60 +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Lcommaaccent +ENCODING 315 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 14 1 -5 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +FC +00 +60 +60 +20 +40 +ENDCHAR +STARTCHAR lcommaaccent +ENCODING 316 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 14 0 -5 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +00 +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR Lcaron +ENCODING 317 +SWIDTH 858 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +C180 +C080 +C100 +C000 +C000 +C000 +C000 +C000 +FC00 +ENDCHAR +STARTCHAR lcaron +ENCODING 318 +SWIDTH 542 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +CC +C4 +C8 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Ldot +ENCODING 319 +SWIDTH 858 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +C000 +C000 +C000 +C000 +C180 +C180 +C000 +C000 +FC00 +ENDCHAR +STARTCHAR ldot +ENCODING 320 +SWIDTH 542 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +C0 +C0 +C0 +C0 +CC +CC +C0 +C0 +C0 +ENDCHAR +STARTCHAR Lslash +ENCODING 321 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 7 9 0 0 +BITMAP +60 +60 +78 +70 +E0 +60 +60 +60 +7E +ENDCHAR +STARTCHAR lslash +ENCODING 322 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 9 -1 0 +BITMAP +60 +60 +70 +60 +E0 +60 +60 +60 +60 +ENDCHAR +STARTCHAR Nacute +ENCODING 323 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +18 +30 +00 +C6 +E6 +E6 +D6 +D6 +CE +CE +C6 +C6 +ENDCHAR +STARTCHAR nacute +ENCODING 324 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +18 +30 +00 +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR Ncommaaccent +ENCODING 325 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 14 1 -5 +BITMAP +C6 +E6 +E6 +D6 +D6 +CE +CE +C6 +C6 +00 +18 +18 +08 +10 +ENDCHAR +STARTCHAR ncommaaccent +ENCODING 326 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 -5 +BITMAP +D8 +EC +CC +CC +CC +CC +CC +00 +30 +30 +10 +20 +ENDCHAR +STARTCHAR Ncaron +ENCODING 327 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +6C +38 +00 +C6 +E6 +E6 +D6 +D6 +CE +CE +C6 +C6 +ENDCHAR +STARTCHAR ncaron +ENCODING 328 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +D8 +70 +00 +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR napostrophe +ENCODING 329 +SWIDTH 875 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +C000 +4000 +9B00 +1D80 +1980 +1980 +1980 +1980 +1980 +ENDCHAR +STARTCHAR Eng +ENCODING 330 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +C6 +E6 +E6 +D6 +D6 +CE +CE +C6 +C6 +06 +06 +0C +ENDCHAR +STARTCHAR eng +ENCODING 331 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +D8 +EC +CC +CC +CC +CC +CC +0C +0C +18 +ENDCHAR +STARTCHAR Omacron +ENCODING 332 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +3C +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR omacron +ENCODING 333 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR Obreve +ENCODING 334 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +22 +1C +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR obreve +ENCODING 335 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +44 +38 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR Ohungarumlaut +ENCODING 336 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +1A +2C +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR ohungarumlaut +ENCODING 337 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +34 +58 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR OE +ENCODING 338 +SWIDTH 1000 0 +DWIDTH 13 0 +BBX 11 9 1 0 +BITMAP +3FE0 +6600 +C600 +C600 +C7E0 +C600 +C600 +6600 +3FE0 +ENDCHAR +STARTCHAR oe +ENCODING 339 +SWIDTH 944 0 +DWIDTH 11 0 +BBX 10 7 0 0 +BITMAP +7780 +CCC0 +CCC0 +CFC0 +CC00 +CCC0 +7780 +ENDCHAR +STARTCHAR Racute +ENCODING 340 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +18 +30 +00 +FC +C6 +C6 +C6 +FC +CC +C6 +C6 +C6 +ENDCHAR +STARTCHAR racute +ENCODING 341 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 5 10 0 0 +BITMAP +30 +60 +00 +D8 +F8 +E0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Rcommaaccent +ENCODING 342 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 14 1 -5 +BITMAP +FC +C6 +C6 +C6 +FC +CC +C6 +C6 +C6 +00 +18 +18 +08 +10 +ENDCHAR +STARTCHAR rcommaaccent +ENCODING 343 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 5 12 0 -5 +BITMAP +D8 +F8 +E0 +C0 +C0 +C0 +C0 +00 +60 +60 +20 +40 +ENDCHAR +STARTCHAR Rcaron +ENCODING 344 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +6C +38 +00 +FC +C6 +C6 +C6 +FC +CC +C6 +C6 +C6 +ENDCHAR +STARTCHAR rcaron +ENCODING 345 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 5 10 0 0 +BITMAP +D8 +70 +00 +D8 +F8 +E0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR Sacute +ENCODING 346 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +18 +30 +00 +7C +C6 +C6 +70 +1C +0E +C6 +C6 +7C +ENDCHAR +STARTCHAR sacute +ENCODING 347 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +18 +30 +00 +78 +CC +E0 +38 +1C +CC +78 +ENDCHAR +STARTCHAR Scircumflex +ENCODING 348 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +38 +6C +00 +7C +C6 +C6 +70 +1C +0E +C6 +C6 +7C +ENDCHAR +STARTCHAR scircumflex +ENCODING 349 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +38 +6C +00 +78 +CC +E0 +38 +1C +CC +78 +ENDCHAR +STARTCHAR Scedilla +ENCODING 350 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +7C +C6 +C6 +70 +1C +0E +C6 +C6 +7C +18 +18 +70 +ENDCHAR +STARTCHAR scedilla +ENCODING 351 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +78 +CC +E0 +38 +1C +CC +78 +18 +18 +70 +ENDCHAR +STARTCHAR Scaron +ENCODING 352 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +6C +38 +00 +78 +CC +E0 +78 +1C +CE +7C +ENDCHAR +STARTCHAR scaron +ENCODING 353 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +D8 +70 +00 +78 +CC +E0 +38 +1C +CC +78 +ENDCHAR +STARTCHAR Tcommaaccent +ENCODING 354 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 8 12 0 -3 +BITMAP +FF +18 +18 +18 +18 +18 +18 +18 +18 +0C +0C +38 +ENDCHAR +STARTCHAR tcommaaccent +ENCODING 355 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 12 0 -3 +BITMAP +60 +60 +F0 +60 +60 +60 +60 +68 +70 +30 +30 +E0 +ENDCHAR +STARTCHAR Tcaron +ENCODING 356 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +36 +1C +00 +FF +18 +18 +18 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR tcaron +ENCODING 357 +SWIDTH 594 0 +DWIDTH 9 0 +BBX 8 9 0 0 +BITMAP +63 +61 +F2 +60 +60 +60 +60 +68 +30 +ENDCHAR +STARTCHAR Tbar +ENCODING 358 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +FF +18 +18 +18 +3E +18 +18 +18 +18 +ENDCHAR +STARTCHAR tbar +ENCODING 359 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 9 0 0 +BITMAP +60 +60 +F0 +60 +60 +F8 +60 +68 +30 +ENDCHAR +STARTCHAR Utilde +ENCODING 360 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +34 +58 +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR utilde +ENCODING 361 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +34 +58 +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR Umacron +ENCODING 362 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +3C +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR umacron +ENCODING 363 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR Ubreve +ENCODING 364 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +44 +38 +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR ubreve +ENCODING 365 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +44 +38 +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR Uring +ENCODING 366 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +38 +6C +38 +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR uring +ENCODING 367 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +38 +6C +38 +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR Uhungarumlaut +ENCODING 368 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +34 +58 +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR uhungarumlaut +ENCODING 369 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +34 +58 +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR Uogonek +ENCODING 370 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +30 +30 +1C +ENDCHAR +STARTCHAR uogonek +ENCODING 371 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +CC +CC +CC +CC +CC +DC +7C +30 +30 +1C +ENDCHAR +STARTCHAR Wcircumflex +ENCODING 372 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 12 0 0 +BITMAP +0E00 +1B00 +0000 +CCC0 +CCC0 +CCC0 +4C80 +6D80 +6D80 +3300 +3300 +3300 +ENDCHAR +STARTCHAR wcircumflex +ENCODING 373 +SWIDTH 778 0 +DWIDTH 11 0 +BBX 10 10 0 0 +BITMAP +0E00 +1B00 +0000 +CCC0 +CCC0 +6D80 +6D80 +6D80 +3300 +3300 +ENDCHAR +STARTCHAR Ycircumflex +ENCODING 374 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +1C +36 +00 +C3 +C3 +66 +66 +3C +18 +18 +18 +18 +ENDCHAR +STARTCHAR ycircumflex +ENCODING 375 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 13 0 -3 +BITMAP +38 +6C +00 +C6 +C6 +6C +6C +38 +38 +18 +10 +30 +60 +ENDCHAR +STARTCHAR Ydieresis +ENCODING 376 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +6C +00 +C3 +66 +24 +3C +18 +18 +18 +ENDCHAR +STARTCHAR Zacute +ENCODING 377 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 12 0 0 +BITMAP +0C +18 +00 +FE +06 +0C +18 +30 +30 +60 +C0 +FE +ENDCHAR +STARTCHAR zacute +ENCODING 378 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 10 0 0 +BITMAP +18 +30 +00 +F8 +18 +30 +20 +60 +C0 +F8 +ENDCHAR +STARTCHAR Zdotaccent +ENCODING 379 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 11 0 0 +BITMAP +18 +00 +FE +06 +0C +18 +30 +30 +60 +C0 +FE +ENDCHAR +STARTCHAR zdotaccent +ENCODING 380 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +30 +00 +F8 +18 +30 +20 +60 +C0 +F8 +ENDCHAR +STARTCHAR Zcaron +ENCODING 381 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +6C +38 +00 +FC +18 +30 +30 +60 +C0 +FE +ENDCHAR +STARTCHAR zcaron +ENCODING 382 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 10 0 0 +BITMAP +D8 +70 +00 +F8 +18 +30 +20 +60 +C0 +F8 +ENDCHAR +STARTCHAR uni0186 +ENCODING 390 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 9 1 0 +BITMAP +78 +CC +06 +06 +06 +06 +06 +CC +78 +ENDCHAR +STARTCHAR uni0189 +ENCODING 393 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 9 0 0 +BITMAP +7C +66 +63 +63 +F3 +63 +63 +66 +7C +ENDCHAR +STARTCHAR uni018E +ENCODING 398 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +FC +0C +0C +0C +FC +0C +0C +0C +FC +ENDCHAR +STARTCHAR florin +ENCODING 402 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 11 0 -3 +BITMAP +0E +18 +18 +7C +30 +30 +30 +30 +30 +E0 +C0 +ENDCHAR +STARTCHAR uni0197 +ENCODING 407 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 5 9 0 0 +BITMAP +60 +60 +60 +60 +F8 +60 +60 +60 +60 +ENDCHAR +STARTCHAR uni019A +ENCODING 410 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 9 -1 0 +BITMAP +60 +60 +60 +60 +F8 +60 +60 +60 +60 +ENDCHAR +STARTCHAR uni019D +ENCODING 413 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 12 0 -3 +BITMAP +63 +73 +73 +6B +6B +67 +67 +63 +63 +60 +60 +C0 +ENDCHAR +STARTCHAR uni019F +ENCODING 415 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +3C +66 +C3 +C3 +FF +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR Ohorn +ENCODING 416 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 9 1 0 +BITMAP +3CC0 +6640 +C380 +C300 +C300 +C300 +C300 +6600 +3C00 +ENDCHAR +STARTCHAR ohorn +ENCODING 417 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +7B +CD +CE +CC +CC +CC +78 +ENDCHAR +STARTCHAR uni01A7 +ENCODING 423 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +7C +C6 +C6 +1C +70 +E0 +C6 +C6 +7C +ENDCHAR +STARTCHAR uni01A8 +ENCODING 424 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +1C +70 +E0 +CC +78 +ENDCHAR +STARTCHAR uni01AE +ENCODING 430 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 8 12 0 -3 +BITMAP +FF +18 +18 +18 +18 +18 +18 +18 +18 +18 +18 +0C +ENDCHAR +STARTCHAR Uhorn +ENCODING 431 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 9 1 0 +BITMAP +C780 +C680 +C700 +C600 +C600 +C600 +C600 +6C00 +7C00 +ENDCHAR +STARTCHAR uhorn +ENCODING 432 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +CF +CD +CE +CC +CC +DC +6C +ENDCHAR +STARTCHAR uni01B5 +ENCODING 437 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +FE +06 +0C +18 +7C +30 +60 +C0 +FE +ENDCHAR +STARTCHAR uni01B6 +ENCODING 438 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 7 0 0 +BITMAP +F8 +18 +30 +F8 +60 +C0 +F8 +ENDCHAR +STARTCHAR uni01BB +ENCODING 443 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +78 +CC +0C +18 +FC +60 +C0 +C0 +FC +ENDCHAR +STARTCHAR uni01BC +ENCODING 444 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +7C +60 +C0 +F8 +0C +0C +CC +CC +78 +ENDCHAR +STARTCHAR uni01C0 +ENCODING 448 +SWIDTH 280 0 +DWIDTH 4 0 +BBX 2 12 1 -3 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni01C2 +ENCODING 450 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 12 0 -2 +BITMAP +30 +30 +30 +30 +30 +FC +30 +FC +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni01C3 +ENCODING 451 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 9 1 0 +BITMAP +C0 +C0 +C0 +C0 +C0 +80 +00 +C0 +C0 +ENDCHAR +STARTCHAR uni01CD +ENCODING 461 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +36 +1C +00 +18 +3C +24 +66 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni01CE +ENCODING 462 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +6C +38 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR uni01CF +ENCODING 463 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 5 12 0 0 +BITMAP +D8 +70 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR uni01D0 +ENCODING 464 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 10 -1 0 +BITMAP +D8 +70 +00 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR uni01D1 +ENCODING 465 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +36 +1C +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni01D2 +ENCODING 466 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +6C +38 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR uni01D3 +ENCODING 467 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +6C +38 +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR uni01D4 +ENCODING 468 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +6C +38 +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR uni01D5 +ENCODING 469 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +3C +00 +6C +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR uni01D6 +ENCODING 470 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +78 +00 +6C +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR uni01D7 +ENCODING 471 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 14 1 0 +BITMAP +18 +30 +00 +6C +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR uni01D8 +ENCODING 472 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 0 +BITMAP +18 +30 +00 +6C +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR uni01D9 +ENCODING 473 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 14 1 0 +BITMAP +6C +38 +00 +6C +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR uni01DA +ENCODING 474 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 0 +BITMAP +6C +38 +00 +6C +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR uni01DB +ENCODING 475 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 14 1 0 +BITMAP +30 +18 +00 +6C +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR uni01DC +ENCODING 476 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 0 +BITMAP +60 +30 +00 +6C +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR uni01DD +ENCODING 477 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +0C +FC +CC +CC +78 +ENDCHAR +STARTCHAR uni01DE +ENCODING 478 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 13 0 0 +BITMAP +3C +00 +36 +00 +18 +18 +3C +24 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni01DF +ENCODING 479 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 11 0 0 +BITMAP +78 +00 +6C +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR uni01E0 +ENCODING 480 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 13 0 0 +BITMAP +3C +00 +18 +00 +18 +3C +24 +66 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni01E1 +ENCODING 481 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 11 0 0 +BITMAP +78 +00 +30 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR uni01E2 +ENCODING 482 +SWIDTH 1000 0 +DWIDTH 13 0 +BBX 11 11 1 0 +BITMAP +0F00 +0000 +1FE0 +3600 +2600 +6600 +67E0 +7E00 +C600 +C600 +C7E0 +ENDCHAR +STARTCHAR uni01E3 +ENCODING 483 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 10 9 0 0 +BITMAP +1E00 +0000 +7780 +CCC0 +0CC0 +7FC0 +CC00 +CCC0 +7780 +ENDCHAR +STARTCHAR uni01E4 +ENCODING 484 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 9 9 1 0 +BITMAP +3E00 +6300 +C000 +C000 +CF00 +CF80 +C300 +6300 +3D00 +ENDCHAR +STARTCHAR uni01E5 +ENCODING 485 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +6C +DC +CC +CC +CC +DC +6C +FC +CC +78 +ENDCHAR +STARTCHAR Gcaron +ENCODING 486 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +6C +38 +00 +3E +63 +C0 +C0 +CF +C3 +C3 +63 +3D +ENDCHAR +STARTCHAR gcaron +ENCODING 487 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 13 0 -3 +BITMAP +6C +38 +00 +6C +DC +CC +CC +CC +DC +6C +0C +CC +78 +ENDCHAR +STARTCHAR uni01E8 +ENCODING 488 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 12 1 0 +BITMAP +6C +38 +00 +C6 +CC +D8 +F0 +F0 +D8 +CC +C6 +C3 +ENDCHAR +STARTCHAR uni01E9 +ENCODING 489 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 12 0 0 +BITMAP +D8 +70 +00 +C0 +C0 +CC +D8 +F0 +F0 +D8 +CC +C6 +ENDCHAR +STARTCHAR uni01EA +ENCODING 490 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 -3 +BITMAP +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +30 +30 +1C +ENDCHAR +STARTCHAR uni01EB +ENCODING 491 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +78 +CC +CC +CC +CC +CC +78 +60 +60 +38 +ENDCHAR +STARTCHAR uni01EC +ENCODING 492 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 14 1 -3 +BITMAP +3C +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +30 +30 +1C +ENDCHAR +STARTCHAR uni01ED +ENCODING 493 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 -3 +BITMAP +78 +00 +78 +CC +CC +CC +CC +CC +78 +60 +60 +38 +ENDCHAR +STARTCHAR uni01F0 +ENCODING 496 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 13 -2 -3 +BITMAP +D8 +70 +00 +30 +30 +30 +30 +30 +30 +30 +30 +30 +60 +ENDCHAR +STARTCHAR uni01F4 +ENCODING 500 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +0C +18 +00 +3E +63 +C0 +C0 +CF +C3 +C3 +63 +3D +ENDCHAR +STARTCHAR uni01F5 +ENCODING 501 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 13 0 -3 +BITMAP +18 +30 +00 +6C +DC +CC +CC +CC +DC +6C +0C +CC +78 +ENDCHAR +STARTCHAR uni01F8 +ENCODING 504 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +30 +18 +00 +C6 +E6 +E6 +D6 +D6 +CE +CE +C6 +C6 +ENDCHAR +STARTCHAR uni01F9 +ENCODING 505 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +60 +30 +00 +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR Aringacute +ENCODING 506 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 15 0 0 +BITMAP +0C +18 +00 +18 +24 +18 +18 +18 +3C +24 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR aringacute +ENCODING 507 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 14 0 0 +BITMAP +18 +30 +00 +30 +48 +30 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR AEacute +ENCODING 508 +SWIDTH 1000 0 +DWIDTH 13 0 +BBX 11 12 1 0 +BITMAP +0300 +0600 +0000 +1FE0 +3600 +2600 +6600 +67E0 +7E00 +C600 +C600 +C7E0 +ENDCHAR +STARTCHAR aeacute +ENCODING 509 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 10 10 0 0 +BITMAP +0600 +0C00 +0000 +7780 +CCC0 +0CC0 +7FC0 +CC00 +CCC0 +7780 +ENDCHAR +STARTCHAR Oslashacute +ENCODING 510 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 13 1 -1 +BITMAP +0C +18 +00 +3D +66 +CF +CB +DB +D3 +F3 +66 +7C +80 +ENDCHAR +STARTCHAR oslashacute +ENCODING 511 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 -1 0 +BITMAP +0C +18 +00 +3D +66 +6E +76 +66 +66 +BC +ENDCHAR +STARTCHAR uni0200 +ENCODING 512 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +58 +34 +00 +18 +3C +24 +66 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni0201 +ENCODING 513 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +B0 +68 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR uni0202 +ENCODING 514 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +1C +22 +00 +18 +3C +24 +66 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni0203 +ENCODING 515 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +38 +44 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR uni0204 +ENCODING 516 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +B0 +68 +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR uni0205 +ENCODING 517 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +B0 +68 +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR uni0206 +ENCODING 518 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +70 +88 +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR uni0207 +ENCODING 519 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +38 +44 +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR uni0208 +ENCODING 520 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 5 12 -1 0 +BITMAP +B0 +68 +00 +30 +30 +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni0209 +ENCODING 521 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 10 -2 0 +BITMAP +B0 +68 +00 +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR uni020A +ENCODING 522 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 5 12 0 0 +BITMAP +70 +88 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR uni020B +ENCODING 523 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 10 -1 0 +BITMAP +70 +88 +00 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR uni020C +ENCODING 524 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +58 +34 +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni020D +ENCODING 525 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +B0 +68 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR uni020E +ENCODING 526 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +1C +22 +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni020F +ENCODING 527 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +38 +44 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR uni0210 +ENCODING 528 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +58 +34 +00 +FC +C6 +C6 +C6 +FC +CC +C6 +C6 +C6 +ENDCHAR +STARTCHAR uni0211 +ENCODING 529 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 5 10 0 0 +BITMAP +B0 +68 +00 +D8 +F8 +E0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni0212 +ENCODING 530 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +38 +44 +00 +FC +C6 +C6 +C6 +FC +CC +C6 +C6 +C6 +ENDCHAR +STARTCHAR uni0213 +ENCODING 531 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 5 10 0 0 +BITMAP +70 +88 +00 +D8 +F8 +E0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni0214 +ENCODING 532 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +58 +34 +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR uni0215 +ENCODING 533 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +B0 +68 +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR uni0216 +ENCODING 534 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +38 +44 +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR uni0217 +ENCODING 535 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +38 +44 +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR Scommaaccent +ENCODING 536 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 14 1 -5 +BITMAP +7C +C6 +C6 +70 +1C +0E +C6 +C6 +7C +00 +18 +18 +08 +10 +ENDCHAR +STARTCHAR scommaaccent +ENCODING 537 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 12 0 -5 +BITMAP +78 +CC +E0 +38 +1C +CC +78 +00 +30 +30 +10 +20 +ENDCHAR +STARTCHAR Tcommaaccent +ENCODING 538 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 8 14 0 -5 +BITMAP +FF +18 +18 +18 +18 +18 +18 +18 +18 +00 +18 +18 +08 +10 +ENDCHAR +STARTCHAR tcommaaccent +ENCODING 539 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 14 0 -5 +BITMAP +60 +60 +F0 +60 +60 +60 +60 +68 +30 +00 +30 +30 +10 +20 +ENDCHAR +STARTCHAR uni021E +ENCODING 542 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +6C +38 +00 +C6 +C6 +C6 +C6 +FE +C6 +C6 +C6 +C6 +ENDCHAR +STARTCHAR uni021F +ENCODING 543 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 0 +BITMAP +D8 +70 +00 +C0 +C0 +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR uni0226 +ENCODING 550 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 11 0 0 +BITMAP +18 +00 +18 +3C +24 +66 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni0227 +ENCODING 551 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +30 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR uni0228 +ENCODING 552 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 -3 +BITMAP +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +30 +30 +E0 +ENDCHAR +STARTCHAR uni0229 +ENCODING 553 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +78 +CC +CC +FC +C0 +CC +78 +18 +18 +70 +ENDCHAR +STARTCHAR uni022A +ENCODING 554 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +3C +00 +66 +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni022B +ENCODING 555 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +78 +00 +6C +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR uni022C +ENCODING 556 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +3C +00 +1A +2C +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni022D +ENCODING 557 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 0 +BITMAP +78 +00 +34 +58 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR uni022E +ENCODING 558 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +18 +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni022F +ENCODING 559 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +30 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR uni0230 +ENCODING 560 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +3C +00 +18 +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni0231 +ENCODING 561 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +78 +00 +30 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR uni0232 +ENCODING 562 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 11 0 0 +BITMAP +3C +00 +C3 +C3 +66 +66 +3C +18 +18 +18 +18 +ENDCHAR +STARTCHAR uni0233 +ENCODING 563 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 12 0 -3 +BITMAP +3C +00 +C6 +C6 +6C +6C +38 +38 +18 +10 +30 +60 +ENDCHAR +STARTCHAR uni0250 +ENCODING 592 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 7 0 0 +BITMAP +DC +66 +66 +7C +60 +66 +3C +ENDCHAR +STARTCHAR uni0254 +ENCODING 596 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +0C +0C +0C +CC +78 +ENDCHAR +STARTCHAR uni0258 +ENCODING 600 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +CC +FC +0C +CC +78 +ENDCHAR +STARTCHAR uni0259 +ENCODING 601 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +0C +FC +CC +CC +78 +ENDCHAR +STARTCHAR uni025F +ENCODING 607 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +30 +30 +30 +30 +30 +30 +78 +30 +E0 +ENDCHAR +STARTCHAR uni0265 +ENCODING 613 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 -2 +BITMAP +CC +CC +CC +CC +CC +DC +6C +0C +0C +ENDCHAR +STARTCHAR uni0275 +ENCODING 629 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +78 +CC +CC +FC +CC +CC +78 +ENDCHAR +STARTCHAR uni0279 +ENCODING 633 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 5 7 0 0 +BITMAP +18 +18 +18 +18 +38 +F8 +D8 +ENDCHAR +STARTCHAR uni0287 +ENCODING 647 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 9 0 0 +BITMAP +60 +B0 +30 +30 +30 +30 +78 +30 +30 +ENDCHAR +STARTCHAR uni0288 +ENCODING 648 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 12 0 -3 +BITMAP +60 +60 +F0 +60 +60 +60 +60 +60 +60 +60 +60 +30 +ENDCHAR +STARTCHAR uni0289 +ENCODING 649 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 7 0 0 +BITMAP +CC +CC +CC +FC +CC +DC +6C +ENDCHAR +STARTCHAR uni028C +ENCODING 652 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 7 0 0 +BITMAP +10 +38 +38 +6C +6C +C6 +C6 +ENDCHAR +STARTCHAR uni028D +ENCODING 653 +SWIDTH 778 0 +DWIDTH 11 0 +BBX 10 7 0 0 +BITMAP +3300 +3300 +6D80 +6D80 +6D80 +CCC0 +CCC0 +ENDCHAR +STARTCHAR uni028E +ENCODING 654 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 10 0 0 +BITMAP +0C +18 +10 +30 +38 +38 +6C +6C +C6 +C6 +ENDCHAR +STARTCHAR uni029E +ENCODING 670 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 0 -2 +BITMAP +C6 +66 +36 +1E +1E +36 +66 +06 +06 +ENDCHAR +STARTCHAR uni02BB +ENCODING 699 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 3 1 6 +BITMAP +40 +80 +C0 +ENDCHAR +STARTCHAR afii57929 +ENCODING 700 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 3 1 6 +BITMAP +C0 +40 +80 +ENDCHAR +STARTCHAR afii64937 +ENCODING 701 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 3 1 6 +BITMAP +C0 +80 +40 +ENDCHAR +STARTCHAR circumflex +ENCODING 710 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 2 0 8 +BITMAP +70 +D8 +ENDCHAR +STARTCHAR caron +ENCODING 711 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 2 0 8 +BITMAP +D8 +70 +ENDCHAR +STARTCHAR uni02C8 +ENCODING 712 +SWIDTH 238 0 +DWIDTH 3 0 +BBX 1 3 1 6 +BITMAP +80 +80 +80 +ENDCHAR +STARTCHAR macron +ENCODING 713 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 1 0 8 +BITMAP +F0 +ENDCHAR +STARTCHAR uni02CA +ENCODING 714 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 0 8 +BITMAP +60 +C0 +ENDCHAR +STARTCHAR uni02CB +ENCODING 715 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 0 8 +BITMAP +C0 +60 +ENDCHAR +STARTCHAR uni02CD +ENCODING 717 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 1 0 -2 +BITMAP +F0 +ENDCHAR +STARTCHAR uni02CE +ENCODING 718 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 0 -3 +BITMAP +C0 +60 +ENDCHAR +STARTCHAR uni02CF +ENCODING 719 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 0 -3 +BITMAP +60 +C0 +ENDCHAR +STARTCHAR breve +ENCODING 728 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 2 0 8 +BITMAP +88 +70 +ENDCHAR +STARTCHAR dotaccent +ENCODING 729 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 1 1 8 +BITMAP +C0 +ENDCHAR +STARTCHAR ring +ENCODING 730 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 3 0 7 +BITMAP +70 +D8 +70 +ENDCHAR +STARTCHAR ogonek +ENCODING 731 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 4 0 -3 +BITMAP +60 +C0 +C0 +70 +ENDCHAR +STARTCHAR tilde +ENCODING 732 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 2 0 8 +BITMAP +68 +B0 +ENDCHAR +STARTCHAR hungarumlaut +ENCODING 733 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 2 1 8 +BITMAP +68 +B0 +ENDCHAR +STARTCHAR uni02EE +ENCODING 750 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 3 1 6 +BITMAP +D8 +48 +90 +ENDCHAR +STARTCHAR uni037E +ENCODING 894 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 9 1 -2 +BITMAP +C0 +C0 +00 +00 +00 +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR tonos +ENCODING 900 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 0 8 +BITMAP +60 +C0 +ENDCHAR +STARTCHAR dieresistonos +ENCODING 901 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 4 0 8 +BITMAP +30 +60 +00 +D8 +ENDCHAR +STARTCHAR anoteleia +ENCODING 903 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 2 1 3 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR mu +ENCODING 956 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +CC +CC +CC +CC +CC +DC +EC +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni1E00 +ENCODING 7680 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 13 0 -4 +BITMAP +18 +3C +24 +66 +66 +7E +C3 +C3 +C3 +00 +1C +36 +1C +ENDCHAR +STARTCHAR uni1E01 +ENCODING 7681 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 11 0 -4 +BITMAP +78 +CC +0C +7C +CC +CC +76 +00 +38 +6C +38 +ENDCHAR +STARTCHAR uni1E02 +ENCODING 7682 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +30 +00 +FC +C6 +C6 +C6 +FC +C6 +C6 +C6 +FC +ENDCHAR +STARTCHAR uni1E03 +ENCODING 7683 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +60 +00 +C0 +C0 +D8 +EC +CC +CC +CC +EC +D8 +ENDCHAR +STARTCHAR uni1E04 +ENCODING 7684 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +FC +C6 +C6 +C6 +FC +C6 +C6 +C6 +FC +00 +30 +ENDCHAR +STARTCHAR uni1E05 +ENCODING 7685 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 0 -2 +BITMAP +C0 +C0 +D8 +EC +CC +CC +CC +EC +D8 +00 +30 +ENDCHAR +STARTCHAR uni1E06 +ENCODING 7686 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +FC +C6 +C6 +C6 +FC +C6 +C6 +C6 +FC +00 +78 +ENDCHAR +STARTCHAR uni1E07 +ENCODING 7687 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 0 -2 +BITMAP +C0 +C0 +D8 +EC +CC +CC +CC +EC +D8 +00 +78 +ENDCHAR +STARTCHAR uni1E08 +ENCODING 7688 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 7 15 1 -3 +BITMAP +18 +30 +00 +3C +66 +C0 +C0 +C0 +C0 +C0 +66 +3C +18 +18 +70 +ENDCHAR +STARTCHAR uni1E09 +ENCODING 7689 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 13 0 -3 +BITMAP +18 +30 +00 +78 +CC +C0 +C0 +C0 +CC +78 +10 +18 +70 +ENDCHAR +STARTCHAR uni1E0A +ENCODING 7690 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +30 +00 +F8 +CC +C6 +C6 +C6 +C6 +C6 +CC +F8 +ENDCHAR +STARTCHAR uni1E0B +ENCODING 7691 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +18 +00 +0C +0C +6C +DC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR uni1E0C +ENCODING 7692 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +F8 +CC +C6 +C6 +C6 +C6 +C6 +CC +F8 +00 +30 +ENDCHAR +STARTCHAR uni1E0D +ENCODING 7693 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 0 -2 +BITMAP +0C +0C +6C +DC +CC +CC +CC +DC +6C +00 +30 +ENDCHAR +STARTCHAR uni1E0E +ENCODING 7694 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +F8 +CC +C6 +C6 +C6 +C6 +C6 +CC +F8 +00 +78 +ENDCHAR +STARTCHAR uni1E0F +ENCODING 7695 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 0 -2 +BITMAP +0C +0C +6C +DC +CC +CC +CC +DC +6C +00 +78 +ENDCHAR +STARTCHAR uni1E10 +ENCODING 7696 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +F8 +CC +C6 +C6 +C6 +C6 +C6 +CC +F8 +18 +18 +70 +ENDCHAR +STARTCHAR uni1E11 +ENCODING 7697 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 -3 +BITMAP +0C +0C +6C +DC +CC +CC +CC +DC +7C +18 +18 +70 +ENDCHAR +STARTCHAR uni1E12 +ENCODING 7698 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +F8 +CC +C6 +C6 +C6 +C6 +C6 +CC +F8 +00 +38 +6C +ENDCHAR +STARTCHAR uni1E13 +ENCODING 7699 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 -3 +BITMAP +0C +0C +6C +DC +CC +CC +CC +DC +6C +00 +38 +6C +ENDCHAR +STARTCHAR uni1E14 +ENCODING 7700 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 14 1 0 +BITMAP +60 +30 +00 +F0 +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR uni1E15 +ENCODING 7701 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 12 0 0 +BITMAP +60 +30 +00 +78 +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR uni1E16 +ENCODING 7702 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 14 1 0 +BITMAP +18 +30 +00 +F0 +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR uni1E17 +ENCODING 7703 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 12 0 0 +BITMAP +18 +30 +00 +78 +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR uni1E18 +ENCODING 7704 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 -3 +BITMAP +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +00 +70 +D8 +ENDCHAR +STARTCHAR uni1E19 +ENCODING 7705 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +78 +CC +CC +FC +C0 +CC +78 +00 +38 +6C +ENDCHAR +STARTCHAR uni1E1A +ENCODING 7706 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 -3 +BITMAP +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +00 +68 +B0 +ENDCHAR +STARTCHAR uni1E1B +ENCODING 7707 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +78 +CC +CC +FC +C0 +CC +78 +00 +68 +B0 +ENDCHAR +STARTCHAR uni1E1C +ENCODING 7708 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 15 1 -3 +BITMAP +88 +70 +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +30 +30 +E0 +ENDCHAR +STARTCHAR uni1E1D +ENCODING 7709 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 13 0 -3 +BITMAP +44 +38 +00 +78 +CC +CC +FC +C0 +CC +78 +18 +18 +70 +ENDCHAR +STARTCHAR uni1E1E +ENCODING 7710 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 1 0 +BITMAP +60 +00 +FC +C0 +C0 +C0 +F8 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni1E1F +ENCODING 7711 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 11 0 0 +BITMAP +30 +00 +38 +60 +F0 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR uni1E20 +ENCODING 7712 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +3C +00 +3E +63 +C0 +C0 +CF +C3 +C3 +63 +3D +ENDCHAR +STARTCHAR uni1E21 +ENCODING 7713 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 -3 +BITMAP +78 +00 +6C +DC +CC +CC +CC +DC +6C +0C +CC +78 +ENDCHAR +STARTCHAR uni1E22 +ENCODING 7714 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +18 +00 +C6 +C6 +C6 +C6 +FE +C6 +C6 +C6 +C6 +ENDCHAR +STARTCHAR uni1E23 +ENCODING 7715 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +60 +00 +C0 +C0 +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR uni1E24 +ENCODING 7716 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +C6 +C6 +C6 +C6 +FE +C6 +C6 +C6 +C6 +00 +18 +ENDCHAR +STARTCHAR uni1E25 +ENCODING 7717 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 0 -2 +BITMAP +C0 +C0 +D8 +EC +CC +CC +CC +CC +CC +00 +30 +ENDCHAR +STARTCHAR uni1E26 +ENCODING 7718 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +6C +00 +C6 +C6 +C6 +C6 +FE +C6 +C6 +C6 +C6 +ENDCHAR +STARTCHAR uni1E27 +ENCODING 7719 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +D8 +00 +C0 +C0 +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR uni1E28 +ENCODING 7720 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +C6 +C6 +C6 +C6 +FE +C6 +C6 +C6 +F6 +18 +18 +70 +ENDCHAR +STARTCHAR uni1E29 +ENCODING 7721 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 -3 +BITMAP +C0 +C0 +D8 +EC +CC +CC +CC +CC +FC +18 +18 +70 +ENDCHAR +STARTCHAR uni1E2A +ENCODING 7722 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +C6 +C6 +C6 +C6 +FE +C6 +C6 +C6 +C6 +00 +44 +38 +ENDCHAR +STARTCHAR uni1E2B +ENCODING 7723 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 -3 +BITMAP +C0 +C0 +D8 +EC +CC +CC +CC +CC +CC +00 +44 +38 +ENDCHAR +STARTCHAR uni1E2C +ENCODING 7724 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 5 12 -1 -3 +BITMAP +30 +30 +30 +30 +30 +30 +30 +30 +30 +00 +68 +B0 +ENDCHAR +STARTCHAR uni1E2D +ENCODING 7725 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 12 -2 -3 +BITMAP +30 +00 +30 +30 +30 +30 +30 +30 +30 +00 +68 +B0 +ENDCHAR +STARTCHAR uni1E2E +ENCODING 7726 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 5 14 0 0 +BITMAP +30 +60 +00 +D8 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR uni1E2F +ENCODING 7727 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 12 -1 0 +BITMAP +30 +60 +00 +D8 +00 +60 +60 +60 +60 +60 +60 +60 +ENDCHAR +STARTCHAR uni1E30 +ENCODING 7728 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 12 1 0 +BITMAP +18 +30 +00 +C6 +CC +D8 +F0 +F0 +D8 +CC +C6 +C3 +ENDCHAR +STARTCHAR uni1E31 +ENCODING 7729 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 12 0 0 +BITMAP +30 +60 +00 +C0 +C0 +CC +D8 +F0 +F0 +D8 +CC +C6 +ENDCHAR +STARTCHAR uni1E32 +ENCODING 7730 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 11 1 -2 +BITMAP +C6 +CC +D8 +F0 +F0 +D8 +CC +C6 +C3 +00 +18 +ENDCHAR +STARTCHAR uni1E33 +ENCODING 7731 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 11 0 -2 +BITMAP +C0 +C0 +CC +D8 +F0 +F0 +D8 +CC +C6 +00 +30 +ENDCHAR +STARTCHAR uni1E34 +ENCODING 7732 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 11 1 -2 +BITMAP +C6 +CC +D8 +F0 +F0 +D8 +CC +C6 +C3 +00 +3C +ENDCHAR +STARTCHAR uni1E35 +ENCODING 7733 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 11 0 -2 +BITMAP +C0 +C0 +CC +D8 +F0 +F0 +D8 +CC +C6 +00 +78 +ENDCHAR +STARTCHAR uni1E36 +ENCODING 7734 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 1 -2 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +FC +00 +60 +ENDCHAR +STARTCHAR uni1E37 +ENCODING 7735 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 11 0 -2 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +00 +C0 +ENDCHAR +STARTCHAR uni1E38 +ENCODING 7736 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 13 1 -2 +BITMAP +F0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +FC +00 +60 +ENDCHAR +STARTCHAR uni1E39 +ENCODING 7737 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 13 -1 -2 +BITMAP +F0 +00 +60 +60 +60 +60 +60 +60 +60 +60 +60 +00 +60 +ENDCHAR +STARTCHAR uni1E3A +ENCODING 7738 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 1 -2 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +FC +00 +F0 +ENDCHAR +STARTCHAR uni1E3B +ENCODING 7739 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 11 -1 -2 +BITMAP +60 +60 +60 +60 +60 +60 +60 +60 +60 +00 +F0 +ENDCHAR +STARTCHAR uni1E3C +ENCODING 7740 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 1 -3 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +FC +00 +70 +D8 +ENDCHAR +STARTCHAR uni1E3D +ENCODING 7741 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 12 -1 -3 +BITMAP +60 +60 +60 +60 +60 +60 +60 +60 +60 +00 +70 +D8 +ENDCHAR +STARTCHAR uni1E3E +ENCODING 7742 +SWIDTH 833 0 +DWIDTH 11 0 +BBX 9 12 1 0 +BITMAP +0C00 +1800 +0000 +C180 +C180 +E380 +E380 +F780 +D580 +DD80 +C980 +C980 +ENDCHAR +STARTCHAR uni1E3F +ENCODING 7743 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 10 10 0 0 +BITMAP +0600 +0C00 +0000 +BB80 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +ENDCHAR +STARTCHAR uni1E40 +ENCODING 7744 +SWIDTH 833 0 +DWIDTH 11 0 +BBX 9 11 1 0 +BITMAP +0C00 +0000 +C180 +C180 +E380 +E380 +F780 +D580 +DD80 +C980 +C980 +ENDCHAR +STARTCHAR uni1E41 +ENCODING 7745 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 10 9 0 0 +BITMAP +0C00 +0000 +BB80 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +ENDCHAR +STARTCHAR uni1E42 +ENCODING 7746 +SWIDTH 833 0 +DWIDTH 11 0 +BBX 9 11 1 -2 +BITMAP +C180 +C180 +E380 +E380 +F780 +D580 +DD80 +C980 +C980 +0000 +0C00 +ENDCHAR +STARTCHAR uni1E43 +ENCODING 7747 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 10 9 0 -2 +BITMAP +BB80 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +0000 +0C00 +ENDCHAR +STARTCHAR uni1E44 +ENCODING 7748 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +30 +00 +C6 +E6 +E6 +D6 +D6 +CE +CE +C6 +C6 +ENDCHAR +STARTCHAR uni1E45 +ENCODING 7749 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +30 +00 +D8 +EC +CC +CC +CC +CC +CC +ENDCHAR +STARTCHAR uni1E46 +ENCODING 7750 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +C6 +E6 +E6 +D6 +D6 +CE +CE +C6 +C6 +00 +18 +ENDCHAR +STARTCHAR uni1E47 +ENCODING 7751 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 -2 +BITMAP +D8 +EC +CC +CC +CC +CC +CC +00 +30 +ENDCHAR +STARTCHAR uni1E48 +ENCODING 7752 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +C6 +E6 +E6 +D6 +D6 +CE +CE +C6 +C6 +00 +3C +ENDCHAR +STARTCHAR uni1E49 +ENCODING 7753 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 -2 +BITMAP +D8 +EC +CC +CC +CC +CC +CC +00 +78 +ENDCHAR +STARTCHAR uni1E4A +ENCODING 7754 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +C6 +E6 +E6 +D6 +D6 +CE +CE +C6 +C6 +00 +38 +6C +ENDCHAR +STARTCHAR uni1E4B +ENCODING 7755 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +D8 +EC +CC +CC +CC +CC +CC +00 +38 +6C +ENDCHAR +STARTCHAR uni1E4C +ENCODING 7756 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 15 1 0 +BITMAP +0C +18 +00 +1A +2C +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni1E4D +ENCODING 7757 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 13 0 0 +BITMAP +18 +30 +00 +34 +58 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR uni1E4E +ENCODING 7758 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +36 +00 +1A +2C +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni1E4F +ENCODING 7759 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 0 +BITMAP +6C +00 +34 +58 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR uni1E50 +ENCODING 7760 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +30 +18 +00 +3C +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni1E51 +ENCODING 7761 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 0 +BITMAP +60 +30 +00 +78 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR uni1E52 +ENCODING 7762 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +0C +18 +00 +3C +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni1E53 +ENCODING 7763 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 0 +BITMAP +18 +30 +00 +78 +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR uni1E54 +ENCODING 7764 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 12 1 0 +BITMAP +18 +30 +00 +FC +C6 +C6 +C6 +FC +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni1E55 +ENCODING 7765 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 13 0 -3 +BITMAP +18 +30 +00 +D8 +EC +CC +CC +CC +EC +D8 +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni1E56 +ENCODING 7766 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 11 1 0 +BITMAP +30 +00 +FC +C6 +C6 +C6 +FC +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni1E57 +ENCODING 7767 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 -3 +BITMAP +30 +00 +D8 +EC +CC +CC +CC +EC +D8 +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni1E58 +ENCODING 7768 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +30 +00 +FC +C6 +C6 +C6 +FC +CC +C6 +C6 +C6 +ENDCHAR +STARTCHAR uni1E59 +ENCODING 7769 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 5 9 0 0 +BITMAP +30 +00 +D8 +F8 +E0 +C0 +C0 +C0 +C0 +ENDCHAR +STARTCHAR uni1E5A +ENCODING 7770 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +FC +C6 +C6 +C6 +FC +CC +C6 +C6 +C6 +00 +18 +ENDCHAR +STARTCHAR uni1E5B +ENCODING 7771 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +D8 +F8 +E0 +C0 +C0 +C0 +C0 +00 +60 +ENDCHAR +STARTCHAR uni1E5C +ENCODING 7772 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 13 1 -2 +BITMAP +78 +00 +FC +C6 +C6 +C6 +FC +CC +C6 +C6 +C6 +00 +18 +ENDCHAR +STARTCHAR uni1E5D +ENCODING 7773 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 5 11 0 -2 +BITMAP +F0 +00 +D8 +F8 +E0 +C0 +C0 +C0 +C0 +00 +60 +ENDCHAR +STARTCHAR uni1E5E +ENCODING 7774 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +FC +C6 +C6 +C6 +FC +CC +C6 +C6 +C6 +00 +3C +ENDCHAR +STARTCHAR uni1E5F +ENCODING 7775 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +D8 +F8 +E0 +C0 +C0 +C0 +C0 +00 +F0 +ENDCHAR +STARTCHAR uni1E60 +ENCODING 7776 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +18 +00 +7C +C6 +C6 +70 +1C +0E +C6 +C6 +7C +ENDCHAR +STARTCHAR uni1E61 +ENCODING 7777 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +30 +00 +78 +CC +E0 +38 +1C +CC +78 +ENDCHAR +STARTCHAR uni1E62 +ENCODING 7778 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +7C +C6 +C6 +70 +1C +0E +C6 +C6 +7C +00 +18 +ENDCHAR +STARTCHAR uni1E63 +ENCODING 7779 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 -2 +BITMAP +78 +CC +E0 +38 +1C +CC +78 +00 +30 +ENDCHAR +STARTCHAR uni1E64 +ENCODING 7780 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 14 1 0 +BITMAP +18 +00 +18 +30 +00 +7C +C6 +C6 +70 +1C +0E +C6 +C6 +7C +ENDCHAR +STARTCHAR uni1E65 +ENCODING 7781 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 12 0 0 +BITMAP +30 +00 +18 +30 +00 +78 +CC +E0 +38 +1C +CC +78 +ENDCHAR +STARTCHAR uni1E66 +ENCODING 7782 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +18 +00 +6C +38 +00 +78 +CC +E0 +78 +1C +CE +7C +ENDCHAR +STARTCHAR uni1E67 +ENCODING 7783 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 12 0 0 +BITMAP +30 +00 +D8 +70 +00 +78 +CC +E0 +38 +1C +CC +78 +ENDCHAR +STARTCHAR uni1E68 +ENCODING 7784 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 13 1 -2 +BITMAP +18 +00 +7C +C6 +C6 +70 +1C +0E +C6 +C6 +7C +00 +18 +ENDCHAR +STARTCHAR uni1E69 +ENCODING 7785 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 11 0 -2 +BITMAP +30 +00 +78 +CC +E0 +38 +1C +CC +78 +00 +30 +ENDCHAR +STARTCHAR uni1E6A +ENCODING 7786 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 8 11 0 0 +BITMAP +18 +00 +FF +18 +18 +18 +18 +18 +18 +18 +18 +ENDCHAR +STARTCHAR uni1E6B +ENCODING 7787 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 11 0 0 +BITMAP +60 +00 +60 +60 +F0 +60 +60 +60 +60 +68 +30 +ENDCHAR +STARTCHAR uni1E6C +ENCODING 7788 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 8 11 0 -2 +BITMAP +FF +18 +18 +18 +18 +18 +18 +18 +18 +00 +18 +ENDCHAR +STARTCHAR uni1E6D +ENCODING 7789 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 11 0 -2 +BITMAP +60 +60 +F0 +60 +60 +60 +60 +68 +30 +00 +30 +ENDCHAR +STARTCHAR uni1E6E +ENCODING 7790 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 8 11 0 -2 +BITMAP +FF +18 +18 +18 +18 +18 +18 +18 +18 +00 +3C +ENDCHAR +STARTCHAR uni1E6F +ENCODING 7791 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 11 0 -2 +BITMAP +60 +60 +F0 +60 +60 +60 +60 +68 +30 +00 +78 +ENDCHAR +STARTCHAR uni1E70 +ENCODING 7792 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 8 12 0 -3 +BITMAP +FF +18 +18 +18 +18 +18 +18 +18 +18 +00 +1C +36 +ENDCHAR +STARTCHAR uni1E71 +ENCODING 7793 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 12 0 -3 +BITMAP +60 +60 +F0 +60 +60 +60 +60 +68 +30 +00 +70 +D8 +ENDCHAR +STARTCHAR uni1E72 +ENCODING 7794 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +00 +6C +ENDCHAR +STARTCHAR uni1E73 +ENCODING 7795 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 -2 +BITMAP +CC +CC +CC +CC +CC +DC +6C +00 +6C +ENDCHAR +STARTCHAR uni1E74 +ENCODING 7796 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +00 +34 +58 +ENDCHAR +STARTCHAR uni1E75 +ENCODING 7797 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +CC +CC +CC +CC +CC +DC +6C +00 +68 +B0 +ENDCHAR +STARTCHAR uni1E76 +ENCODING 7798 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +00 +38 +6C +ENDCHAR +STARTCHAR uni1E77 +ENCODING 7799 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 10 0 -3 +BITMAP +CC +CC +CC +CC +CC +DC +6C +00 +38 +6C +ENDCHAR +STARTCHAR uni1E78 +ENCODING 7800 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 15 1 0 +BITMAP +18 +30 +00 +34 +58 +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR uni1E79 +ENCODING 7801 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 13 0 0 +BITMAP +18 +30 +00 +34 +58 +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR uni1E7A +ENCODING 7802 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +6C +00 +3C +00 +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +ENDCHAR +STARTCHAR uni1E7B +ENCODING 7803 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 0 0 +BITMAP +6C +00 +78 +00 +CC +CC +CC +CC +CC +DC +6C +ENDCHAR +STARTCHAR uni1E7C +ENCODING 7804 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +1A +2C +00 +C3 +C3 +66 +66 +66 +24 +3C +18 +18 +ENDCHAR +STARTCHAR uni1E7D +ENCODING 7805 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 10 0 0 +BITMAP +34 +58 +00 +C6 +C6 +6C +6C +38 +38 +10 +ENDCHAR +STARTCHAR uni1E7E +ENCODING 7806 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 11 0 -2 +BITMAP +C3 +C3 +66 +66 +66 +24 +3C +18 +18 +00 +18 +ENDCHAR +STARTCHAR uni1E7F +ENCODING 7807 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 9 0 -2 +BITMAP +C6 +C6 +6C +6C +38 +38 +10 +00 +18 +ENDCHAR +STARTCHAR Wgrave +ENCODING 7808 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 12 0 0 +BITMAP +1800 +0C00 +0000 +CCC0 +CCC0 +CCC0 +4C80 +6D80 +6D80 +3300 +3300 +3300 +ENDCHAR +STARTCHAR wgrave +ENCODING 7809 +SWIDTH 778 0 +DWIDTH 11 0 +BBX 10 10 0 0 +BITMAP +1800 +0C00 +0000 +CCC0 +CCC0 +6D80 +6D80 +6D80 +3300 +3300 +ENDCHAR +STARTCHAR Wacute +ENCODING 7810 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 12 0 0 +BITMAP +0600 +0C00 +0000 +CCC0 +CCC0 +CCC0 +4C80 +6D80 +6D80 +3300 +3300 +3300 +ENDCHAR +STARTCHAR wacute +ENCODING 7811 +SWIDTH 778 0 +DWIDTH 11 0 +BBX 10 10 0 0 +BITMAP +0600 +0C00 +0000 +CCC0 +CCC0 +6D80 +6D80 +6D80 +3300 +3300 +ENDCHAR +STARTCHAR Wdieresis +ENCODING 7812 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 11 0 0 +BITMAP +1B00 +0000 +CCC0 +CCC0 +CCC0 +4C80 +6D80 +6D80 +3300 +3300 +3300 +ENDCHAR +STARTCHAR wdieresis +ENCODING 7813 +SWIDTH 778 0 +DWIDTH 11 0 +BBX 10 9 0 0 +BITMAP +1B00 +0000 +CCC0 +CCC0 +6D80 +6D80 +6D80 +3300 +3300 +ENDCHAR +STARTCHAR uni1E86 +ENCODING 7814 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 11 0 0 +BITMAP +0C00 +0000 +CCC0 +CCC0 +CCC0 +4C80 +6D80 +6D80 +3300 +3300 +3300 +ENDCHAR +STARTCHAR uni1E87 +ENCODING 7815 +SWIDTH 778 0 +DWIDTH 11 0 +BBX 10 9 0 0 +BITMAP +0C00 +0000 +CCC0 +CCC0 +6D80 +6D80 +6D80 +3300 +3300 +ENDCHAR +STARTCHAR uni1E88 +ENCODING 7816 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 11 0 -2 +BITMAP +CCC0 +CCC0 +CCC0 +4C80 +6D80 +6D80 +3300 +3300 +3300 +0000 +0C00 +ENDCHAR +STARTCHAR uni1E89 +ENCODING 7817 +SWIDTH 778 0 +DWIDTH 11 0 +BBX 10 9 0 -2 +BITMAP +CCC0 +CCC0 +6D80 +6D80 +6D80 +3300 +3300 +0000 +0C00 +ENDCHAR +STARTCHAR uni1E8A +ENCODING 7818 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 11 0 0 +BITMAP +18 +00 +C3 +C3 +66 +3C +18 +3C +66 +C3 +C3 +ENDCHAR +STARTCHAR uni1E8B +ENCODING 7819 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +30 +00 +CC +CC +78 +30 +78 +CC +CC +ENDCHAR +STARTCHAR uni1E8C +ENCODING 7820 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 11 0 0 +BITMAP +36 +00 +C3 +C3 +66 +3C +18 +3C +66 +C3 +C3 +ENDCHAR +STARTCHAR uni1E8D +ENCODING 7821 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +6C +00 +CC +CC +78 +30 +78 +CC +CC +ENDCHAR +STARTCHAR uni1E8E +ENCODING 7822 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 11 0 0 +BITMAP +18 +00 +C3 +C3 +66 +66 +3C +18 +18 +18 +18 +ENDCHAR +STARTCHAR uni1E8F +ENCODING 7823 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 12 0 -3 +BITMAP +18 +00 +C6 +C6 +6C +6C +38 +38 +18 +10 +30 +60 +ENDCHAR +STARTCHAR uni1E90 +ENCODING 7824 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 12 0 0 +BITMAP +38 +6C +00 +FE +06 +0C +18 +30 +30 +60 +C0 +FE +ENDCHAR +STARTCHAR uni1E91 +ENCODING 7825 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 10 0 0 +BITMAP +70 +D8 +00 +F8 +18 +30 +20 +60 +C0 +F8 +ENDCHAR +STARTCHAR uni1E92 +ENCODING 7826 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 11 0 -2 +BITMAP +FE +06 +0C +18 +30 +30 +60 +C0 +FE +00 +30 +ENDCHAR +STARTCHAR uni1E93 +ENCODING 7827 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 9 0 -2 +BITMAP +F8 +18 +30 +20 +60 +C0 +F8 +00 +60 +ENDCHAR +STARTCHAR uni1E94 +ENCODING 7828 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 11 0 -2 +BITMAP +FE +06 +0C +18 +30 +30 +60 +C0 +FE +00 +78 +ENDCHAR +STARTCHAR uni1E95 +ENCODING 7829 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 9 0 -2 +BITMAP +F8 +18 +30 +20 +60 +C0 +F8 +00 +F0 +ENDCHAR +STARTCHAR uni1E96 +ENCODING 7830 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 0 -2 +BITMAP +C0 +C0 +D8 +EC +CC +CC +CC +CC +CC +00 +78 +ENDCHAR +STARTCHAR uni1E97 +ENCODING 7831 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 11 0 0 +BITMAP +D8 +00 +60 +60 +F0 +60 +60 +60 +60 +68 +30 +ENDCHAR +STARTCHAR uni1E98 +ENCODING 7832 +SWIDTH 778 0 +DWIDTH 11 0 +BBX 10 11 0 0 +BITMAP +0E00 +1B00 +0E00 +0000 +CCC0 +CCC0 +6D80 +6D80 +6D80 +3300 +3300 +ENDCHAR +STARTCHAR uni1E99 +ENCODING 7833 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 14 0 -3 +BITMAP +38 +6C +38 +00 +C6 +C6 +6C +6C +38 +38 +18 +10 +30 +60 +ENDCHAR +STARTCHAR uni1EA0 +ENCODING 7840 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 11 0 -2 +BITMAP +18 +3C +24 +66 +66 +7E +C3 +C3 +C3 +00 +18 +ENDCHAR +STARTCHAR uni1EA1 +ENCODING 7841 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 0 -2 +BITMAP +78 +CC +0C +7C +CC +CC +76 +00 +18 +ENDCHAR +STARTCHAR uni1EA4 +ENCODING 7844 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 15 0 0 +BITMAP +0C +18 +00 +1C +36 +00 +18 +18 +3C +24 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni1EA5 +ENCODING 7845 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 13 0 0 +BITMAP +18 +30 +00 +38 +6C +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR uni1EA6 +ENCODING 7846 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 15 0 0 +BITMAP +30 +18 +00 +1C +36 +00 +18 +18 +3C +24 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni1EA7 +ENCODING 7847 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 13 0 0 +BITMAP +30 +18 +00 +38 +6C +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR uni1EAA +ENCODING 7850 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 15 0 0 +BITMAP +1A +2C +00 +1C +36 +00 +18 +18 +3C +24 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni1EAB +ENCODING 7851 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 13 0 0 +BITMAP +34 +58 +00 +38 +6C +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR uni1EAC +ENCODING 7852 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 14 0 -2 +BITMAP +1C +36 +00 +18 +3C +24 +66 +66 +7E +C3 +C3 +C3 +00 +18 +ENDCHAR +STARTCHAR uni1EAD +ENCODING 7853 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 12 0 -2 +BITMAP +38 +6C +00 +78 +CC +0C +7C +CC +CC +76 +00 +18 +ENDCHAR +STARTCHAR uni1EAE +ENCODING 7854 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 15 0 0 +BITMAP +0C +18 +00 +22 +1C +00 +18 +3C +24 +66 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni1EAF +ENCODING 7855 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 13 0 0 +BITMAP +18 +30 +00 +44 +38 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR uni1EB0 +ENCODING 7856 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 15 0 0 +BITMAP +30 +18 +00 +22 +1C +00 +18 +3C +24 +66 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni1EB1 +ENCODING 7857 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 13 0 0 +BITMAP +30 +18 +00 +44 +38 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR uni1EB4 +ENCODING 7860 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 15 0 0 +BITMAP +1A +2C +00 +22 +1C +00 +18 +3C +24 +66 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni1EB5 +ENCODING 7861 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 13 0 0 +BITMAP +34 +58 +00 +44 +38 +00 +78 +CC +0C +7C +CC +CC +76 +ENDCHAR +STARTCHAR uni1EB6 +ENCODING 7862 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 14 0 -2 +BITMAP +22 +1C +00 +18 +3C +24 +66 +66 +7E +C3 +C3 +C3 +00 +18 +ENDCHAR +STARTCHAR uni1EB7 +ENCODING 7863 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 12 0 -2 +BITMAP +44 +38 +00 +78 +CC +0C +7C +CC +CC +76 +00 +18 +ENDCHAR +STARTCHAR uni1EB8 +ENCODING 7864 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 11 1 -2 +BITMAP +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +00 +60 +ENDCHAR +STARTCHAR uni1EB9 +ENCODING 7865 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 -2 +BITMAP +78 +CC +CC +FC +C0 +CC +78 +00 +30 +ENDCHAR +STARTCHAR uni1EBC +ENCODING 7868 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +68 +B0 +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR uni1EBD +ENCODING 7869 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 0 0 +BITMAP +34 +58 +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR uni1EBE +ENCODING 7870 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 15 1 0 +BITMAP +18 +30 +00 +38 +6C +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR uni1EBF +ENCODING 7871 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 13 0 0 +BITMAP +18 +30 +00 +38 +6C +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR uni1EC0 +ENCODING 7872 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 15 1 0 +BITMAP +60 +30 +00 +38 +6C +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR uni1EC1 +ENCODING 7873 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 13 0 0 +BITMAP +30 +18 +00 +38 +6C +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR uni1EC4 +ENCODING 7876 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 15 1 0 +BITMAP +34 +58 +00 +38 +6C +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +ENDCHAR +STARTCHAR uni1EC5 +ENCODING 7877 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 13 0 0 +BITMAP +34 +58 +00 +38 +6C +00 +78 +CC +CC +FC +C0 +CC +78 +ENDCHAR +STARTCHAR uni1EC6 +ENCODING 7878 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 14 1 -2 +BITMAP +70 +D8 +00 +FC +C0 +C0 +C0 +FC +C0 +C0 +C0 +FC +00 +60 +ENDCHAR +STARTCHAR uni1EC7 +ENCODING 7879 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 12 0 -2 +BITMAP +38 +6C +00 +78 +CC +CC +FC +C0 +CC +78 +00 +30 +ENDCHAR +STARTCHAR uni1ECA +ENCODING 7882 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 11 1 -2 +BITMAP +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +00 +C0 +ENDCHAR +STARTCHAR uni1ECB +ENCODING 7883 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 11 0 -2 +BITMAP +C0 +00 +C0 +C0 +C0 +C0 +C0 +C0 +C0 +00 +C0 +ENDCHAR +STARTCHAR uni1ECC +ENCODING 7884 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 11 1 -2 +BITMAP +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +00 +18 +ENDCHAR +STARTCHAR uni1ECD +ENCODING 7885 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 -2 +BITMAP +78 +CC +CC +CC +CC +CC +78 +00 +30 +ENDCHAR +STARTCHAR uni1ED0 +ENCODING 7888 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 15 1 0 +BITMAP +0C +18 +00 +1C +36 +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni1ED1 +ENCODING 7889 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 13 0 0 +BITMAP +18 +30 +00 +38 +6C +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR uni1ED2 +ENCODING 7890 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 15 1 0 +BITMAP +30 +18 +00 +1C +36 +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni1ED3 +ENCODING 7891 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 13 0 0 +BITMAP +30 +18 +00 +38 +6C +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR uni1ED6 +ENCODING 7894 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 15 1 0 +BITMAP +1A +2C +00 +1C +36 +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +ENDCHAR +STARTCHAR uni1ED7 +ENCODING 7895 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 13 0 0 +BITMAP +34 +58 +00 +38 +6C +00 +78 +CC +CC +CC +CC +CC +78 +ENDCHAR +STARTCHAR uni1ED8 +ENCODING 7896 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 14 1 -2 +BITMAP +1C +36 +00 +3C +66 +C3 +C3 +C3 +C3 +C3 +66 +3C +00 +18 +ENDCHAR +STARTCHAR uni1ED9 +ENCODING 7897 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 0 -2 +BITMAP +38 +6C +00 +78 +CC +CC +CC +CC +CC +78 +00 +30 +ENDCHAR +STARTCHAR uni1EDA +ENCODING 7898 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 12 1 0 +BITMAP +0600 +0C00 +0000 +3CC0 +6640 +C380 +C300 +C300 +C300 +C300 +6600 +3C00 +ENDCHAR +STARTCHAR uni1EDB +ENCODING 7899 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +0C +18 +00 +7B +CD +CE +CC +CC +CC +78 +ENDCHAR +STARTCHAR uni1EDC +ENCODING 7900 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 12 1 0 +BITMAP +1800 +0C00 +0000 +3CC0 +6640 +C380 +C300 +C300 +C300 +C300 +6600 +3C00 +ENDCHAR +STARTCHAR uni1EDD +ENCODING 7901 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +30 +18 +00 +7B +CD +CE +CC +CC +CC +78 +ENDCHAR +STARTCHAR uni1EE0 +ENCODING 7904 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 12 1 0 +BITMAP +0D00 +1600 +0000 +3CC0 +6640 +C380 +C300 +C300 +C300 +C300 +6600 +3C00 +ENDCHAR +STARTCHAR uni1EE1 +ENCODING 7905 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +1A +2C +00 +7B +CD +CE +CC +CC +CC +78 +ENDCHAR +STARTCHAR uni1EE2 +ENCODING 7906 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 11 1 -2 +BITMAP +3CC0 +6640 +C380 +C300 +C300 +C300 +C300 +6600 +3C00 +0000 +1800 +ENDCHAR +STARTCHAR uni1EE3 +ENCODING 7907 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 -2 +BITMAP +7B +CD +CE +CC +CC +CC +78 +00 +30 +ENDCHAR +STARTCHAR uni1EE4 +ENCODING 7908 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +C6 +C6 +C6 +C6 +C6 +C6 +C6 +6C +7C +00 +18 +ENDCHAR +STARTCHAR uni1EE5 +ENCODING 7909 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 -2 +BITMAP +CC +CC +CC +CC +CC +DC +6C +00 +30 +ENDCHAR +STARTCHAR uni1EE8 +ENCODING 7912 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 12 1 0 +BITMAP +0C00 +1800 +0000 +C780 +C680 +C700 +C600 +C600 +C600 +C600 +6C00 +7C00 +ENDCHAR +STARTCHAR uni1EE9 +ENCODING 7913 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +0C +18 +00 +CF +CD +CE +CC +CC +DC +6C +ENDCHAR +STARTCHAR uni1EEA +ENCODING 7914 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 12 1 0 +BITMAP +1800 +0C00 +0000 +C780 +C680 +C700 +C600 +C600 +C600 +C600 +6C00 +7C00 +ENDCHAR +STARTCHAR uni1EEB +ENCODING 7915 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +30 +18 +00 +CF +CD +CE +CC +CC +DC +6C +ENDCHAR +STARTCHAR uni1EEE +ENCODING 7918 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 12 1 0 +BITMAP +1A00 +2C00 +0000 +C780 +C680 +C700 +C600 +C600 +C600 +C600 +6C00 +7C00 +ENDCHAR +STARTCHAR uni1EEF +ENCODING 7919 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +1A +2C +00 +CF +CD +CE +CC +CC +DC +6C +ENDCHAR +STARTCHAR uni1EF0 +ENCODING 7920 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 11 1 -2 +BITMAP +C780 +C680 +C700 +C600 +C600 +C600 +C600 +6C00 +7C00 +0000 +1800 +ENDCHAR +STARTCHAR uni1EF1 +ENCODING 7921 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 -2 +BITMAP +CF +CD +CE +CC +CC +DC +6C +00 +18 +ENDCHAR +STARTCHAR Ygrave +ENCODING 7922 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +30 +18 +00 +C3 +C3 +66 +66 +3C +18 +18 +18 +18 +ENDCHAR +STARTCHAR ygrave +ENCODING 7923 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 13 0 -3 +BITMAP +30 +18 +00 +C6 +C6 +6C +6C +38 +38 +18 +10 +30 +60 +ENDCHAR +STARTCHAR uni1EF4 +ENCODING 7924 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 11 0 -2 +BITMAP +C3 +C3 +66 +66 +3C +18 +18 +18 +18 +00 +18 +ENDCHAR +STARTCHAR uni1EF5 +ENCODING 7925 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 12 0 -5 +BITMAP +C6 +C6 +6C +6C +38 +38 +18 +10 +30 +60 +00 +30 +ENDCHAR +STARTCHAR uni1EF8 +ENCODING 7928 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +1A +2C +00 +C3 +C3 +66 +66 +3C +18 +18 +18 +18 +ENDCHAR +STARTCHAR uni1EF9 +ENCODING 7929 +SWIDTH 556 0 +DWIDTH 8 0 +BBX 7 13 0 -3 +BITMAP +34 +58 +00 +C6 +C6 +6C +6C +38 +38 +18 +10 +30 +60 +ENDCHAR +STARTCHAR uni2000 +ENCODING 8192 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2001 +ENCODING 8193 +SWIDTH 1000 0 +DWIDTH 13 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2002 +ENCODING 8194 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2003 +ENCODING 8195 +SWIDTH 1000 0 +DWIDTH 13 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2004 +ENCODING 8196 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2005 +ENCODING 8197 +SWIDTH 250 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2006 +ENCODING 8198 +SWIDTH 167 0 +DWIDTH 2 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2007 +ENCODING 8199 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2008 +ENCODING 8200 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2009 +ENCODING 8201 +SWIDTH 200 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni200A +ENCODING 8202 +SWIDTH 100 0 +DWIDTH 1 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni200B +ENCODING 8203 +SWIDTH 0 0 +DWIDTH 0 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2010 +ENCODING 8208 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 0 3 +BITMAP +F0 +ENDCHAR +STARTCHAR uni2011 +ENCODING 8209 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 0 3 +BITMAP +F0 +ENDCHAR +STARTCHAR figuredash +ENCODING 8210 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 1 0 3 +BITMAP +FE +ENDCHAR +STARTCHAR endash +ENCODING 8211 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 1 0 3 +BITMAP +FE +ENDCHAR +STARTCHAR emdash +ENCODING 8212 +SWIDTH 1000 0 +DWIDTH 12 0 +BBX 12 1 0 3 +BITMAP +FFF0 +ENDCHAR +STARTCHAR afii00208 +ENCODING 8213 +SWIDTH 1000 0 +DWIDTH 12 0 +BBX 12 1 0 3 +BITMAP +FFF0 +ENDCHAR +STARTCHAR quoteleft +ENCODING 8216 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 3 1 6 +BITMAP +40 +80 +C0 +ENDCHAR +STARTCHAR quoteright +ENCODING 8217 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 3 1 6 +BITMAP +C0 +40 +80 +ENDCHAR +STARTCHAR quotesinglbase +ENCODING 8218 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 3 1 -2 +BITMAP +C0 +40 +80 +ENDCHAR +STARTCHAR quotereversed +ENCODING 8219 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 3 1 6 +BITMAP +C0 +80 +40 +ENDCHAR +STARTCHAR quotedblleft +ENCODING 8220 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 3 1 6 +BITMAP +48 +90 +D8 +ENDCHAR +STARTCHAR quotedblright +ENCODING 8221 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 3 1 6 +BITMAP +D8 +48 +90 +ENDCHAR +STARTCHAR quotedblbase +ENCODING 8222 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 3 1 -2 +BITMAP +D8 +48 +90 +ENDCHAR +STARTCHAR uni201F +ENCODING 8223 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 3 1 6 +BITMAP +D8 +90 +48 +ENDCHAR +STARTCHAR dagger +ENCODING 8224 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +FC +30 +30 +30 +30 +30 +30 +30 +30 +ENDCHAR +STARTCHAR daggerdbl +ENCODING 8225 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 12 0 -3 +BITMAP +30 +30 +30 +FC +30 +30 +30 +FC +30 +30 +30 +30 +ENDCHAR +STARTCHAR bullet +ENCODING 8226 +SWIDTH 350 0 +DWIDTH 4 0 +BBX 4 3 0 2 +BITMAP +60 +F0 +60 +ENDCHAR +STARTCHAR ellipsis +ENCODING 8230 +SWIDTH 1000 0 +DWIDTH 12 0 +BBX 10 1 1 0 +BITMAP +CCC0 +ENDCHAR +STARTCHAR perthousand +ENCODING 8240 +SWIDTH 1000 0 +DWIDTH 13 0 +BBX 13 8 0 0 +BITMAP +7100 +DB00 +DA00 +7400 +05B0 +0B68 +1B68 +11B0 +ENDCHAR +STARTCHAR guilsinglleft +ENCODING 8249 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 3 5 1 1 +BITMAP +20 +60 +C0 +60 +20 +ENDCHAR +STARTCHAR guilsinglright +ENCODING 8250 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 3 5 1 1 +BITMAP +80 +C0 +60 +C0 +80 +ENDCHAR +STARTCHAR fraction +ENCODING 8260 +SWIDTH 167 0 +DWIDTH 4 0 +BBX 5 8 -1 0 +BITMAP +18 +18 +30 +30 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR oneinferior +ENCODING 8321 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 5 0 -3 +BITMAP +60 +E0 +60 +60 +60 +ENDCHAR +STARTCHAR twoinferior +ENCODING 8322 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 5 0 -3 +BITMAP +60 +B0 +60 +C0 +F0 +ENDCHAR +STARTCHAR threeinferior +ENCODING 8323 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 5 0 -3 +BITMAP +60 +B0 +60 +30 +E0 +ENDCHAR +STARTCHAR uni20A5 +ENCODING 8357 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 10 9 0 -1 +BITMAP +0600 +BF80 +CCC0 +CCC0 +CCC0 +CCC0 +CCC0 +DCC0 +1800 +ENDCHAR +STARTCHAR uni20A6 +ENCODING 8358 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +C6 +E6 +E6 +FE +D6 +FE +CE +C6 +C6 +ENDCHAR +STARTCHAR uni20A9 +ENCODING 8361 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 9 0 0 +BITMAP +CCC0 +CCC0 +CCC0 +7F80 +6D80 +7F80 +3300 +3300 +3300 +ENDCHAR +STARTCHAR Euro +ENCODING 8364 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 9 -1 0 +BITMAP +0F00 +1980 +3000 +FC00 +3000 +FC00 +3000 +1980 +0F00 +ENDCHAR +STARTCHAR uni20AD +ENCODING 8365 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 9 1 0 +BITMAP +C6 +CC +D8 +F0 +FF +D8 +CC +C6 +C3 +ENDCHAR +STARTCHAR uni2103 +ENCODING 8451 +SWIDTH 1102 0 +DWIDTH 13 0 +BBX 13 9 0 0 +BITMAP +00F0 +6198 +9300 +9300 +6300 +0300 +0300 +0198 +00F0 +ENDCHAR +STARTCHAR uni2109 +ENCODING 8457 +SWIDTH 991 0 +DWIDTH 12 0 +BBX 12 9 0 0 +BITMAP +03F0 +6300 +9300 +9300 +63E0 +0300 +0300 +0300 +0300 +ENDCHAR +STARTCHAR trademark +ENCODING 8482 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 9 5 1 3 +BITMAP +E880 +4D80 +4A80 +4A80 +4A80 +ENDCHAR +STARTCHAR uni212A +ENCODING 8490 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 9 1 0 +BITMAP +C6 +CC +D8 +F0 +F0 +D8 +CC +C6 +C3 +ENDCHAR +STARTCHAR uni212B +ENCODING 8491 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +18 +24 +18 +18 +18 +3C +24 +66 +7E +C3 +C3 +C3 +ENDCHAR +STARTCHAR uni2132 +ENCODING 8498 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +0C +0C +0C +0C +7C +0C +0C +0C +FC +ENDCHAR +STARTCHAR universal +ENCODING 8704 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +C3 +C3 +C3 +7E +66 +66 +24 +3C +18 +ENDCHAR +STARTCHAR existential +ENCODING 8707 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +FC +0C +0C +0C +FC +0C +0C +0C +FC +ENDCHAR +STARTCHAR uni2204 +ENCODING 8708 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +FC +1C +1C +3C +FC +2C +2C +6C +FC +ENDCHAR +STARTCHAR minus +ENCODING 8722 +SWIDTH 584 0 +DWIDTH 8 0 +BBX 5 1 1 3 +BITMAP +F8 +ENDCHAR +STARTCHAR fraction +ENCODING 8725 +SWIDTH 167 0 +DWIDTH 4 0 +BBX 5 8 -1 0 +BITMAP +18 +18 +30 +30 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR periodcentered +ENCODING 8729 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 2 1 3 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR uni2236 +ENCODING 8758 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 7 1 0 +BITMAP +C0 +C0 +00 +00 +00 +C0 +C0 +ENDCHAR +STARTCHAR uni2259 +ENCODING 8793 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 6 0 2 +BITMAP +38 +6C +00 +FC +00 +FC +ENDCHAR +STARTCHAR uni225A +ENCODING 8794 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 6 0 2 +BITMAP +6C +38 +00 +FC +00 +FC +ENDCHAR +STARTCHAR notequal +ENCODING 8800 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 9 0 -1 +BITMAP +18 +18 +10 +FC +30 +FC +20 +60 +60 +ENDCHAR +STARTCHAR equivalence +ENCODING 8801 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 5 0 1 +BITMAP +FC +00 +FC +00 +FC +ENDCHAR +STARTCHAR uni2262 +ENCODING 8802 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 9 0 -1 +BITMAP +18 +18 +FC +30 +FC +20 +FC +60 +60 +ENDCHAR +STARTCHAR lessequal +ENCODING 8804 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 7 1 -1 +BITMAP +18 +70 +C0 +70 +18 +00 +F8 +ENDCHAR +STARTCHAR greaterequal +ENCODING 8805 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 7 1 -1 +BITMAP +C0 +70 +18 +70 +C0 +00 +F8 +ENDCHAR +STARTCHAR uni226E +ENCODING 8814 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 9 1 -1 +BITMAP +18 +18 +18 +70 +F0 +70 +38 +60 +60 +ENDCHAR +STARTCHAR uni226F +ENCODING 8815 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 9 1 -1 +BITMAP +18 +18 +D0 +70 +38 +70 +E0 +60 +60 +ENDCHAR +STARTCHAR uni2270 +ENCODING 8816 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 9 1 -2 +BITMAP +18 +18 +70 +F0 +70 +38 +20 +F8 +60 +ENDCHAR +STARTCHAR uni2271 +ENCODING 8817 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 9 1 -2 +BITMAP +18 +D8 +70 +38 +70 +E0 +20 +F8 +60 +ENDCHAR +STARTCHAR fi +ENCODING -1 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 7 9 0 0 +BITMAP +36 +60 +F6 +66 +66 +66 +66 +66 +66 +ENDCHAR +STARTCHAR fl +ENCODING -1 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 7 9 0 0 +BITMAP +36 +66 +F6 +66 +66 +66 +66 +66 +66 +ENDCHAR +ENDFONT diff --git a/gui/themes/fonts/helvBO12-iso-8859-1.bdf b/gui/themes/fonts/helvBO12-iso-8859-1.bdf new file mode 100644 index 0000000000..9073827992 --- /dev/null +++ b/gui/themes/fonts/helvBO12-iso-8859-1.bdf @@ -0,0 +1,3058 @@ +STARTFONT 2.1 +COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT! +COMMENT Generated with 'ucs2any.pl helvBO12.bdf ../../../fonts/util/map-ISO8859-1 ISO8859-1' +COMMENT from an ISO10646-1 encoded source BDF font. +COMMENT ucs2any.pl by Markus Kuhn <mkuhn@acm.org>, 2000. +FONT -Adobe-Helvetica-Bold-O-Normal--12-120-75-75-P-69-ISO8859-1 +SIZE 12 75 75 +FONTBOUNDINGBOX 16 15 -2 -3 +COMMENT $Xorg: $ +COMMENT ISO10646-1 extension by Markus Kuhn <mkuhn@acm.org>, 2001-03-20 +COMMENT +COMMENT + +COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated. +COMMENT Copyright 1988, 1994 Digital Equipment Corporation. +COMMENT +COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be +COMMENT registered in certain jurisdictions. +COMMENT Permission to use these trademarks is hereby granted only in +COMMENT association with the images described in this file. +COMMENT +COMMENT Permission to use, copy, modify, distribute and sell this software +COMMENT and its documentation for any purpose and without fee is hereby +COMMENT granted, provided that the above copyright notices appear in all +COMMENT copies and that both those copyright notices and this permission +COMMENT notice appear in supporting documentation, and that the names of +COMMENT Adobe Systems and Digital Equipment Corporation not be used in +COMMENT advertising or publicity pertaining to distribution of the software +COMMENT without specific, written prior permission. Adobe Systems and +COMMENT Digital Equipment Corporation make no representations about the +COMMENT suitability of this software for any purpose. It is provided "as +COMMENT is" without express or implied warranty. +COMMENT - +STARTPROPERTIES 26 +FOUNDRY "Adobe" +FAMILY_NAME "Helvetica" +WEIGHT_NAME "Bold" +SLANT "O" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 12 +POINT_SIZE 120 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "P" +AVERAGE_WIDTH 69 +CHARSET_REGISTRY "ISO8859" +CHARSET_ENCODING "1" +CAP_HEIGHT 9 +X_HEIGHT 7 +FONT_ASCENT 11 +FONT_DESCENT 3 +FACE_NAME "Helvetica Bold Oblique" +COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved." +NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. " +_DEC_DEVICE_FONTNAMES "PS=Helvetica-BoldOblique" +DEFAULT_CHAR 0 +RELATIVE_SETWIDTH 50 +RELATIVE_WEIGHT 70 +FULL_NAME "Helvetica Bold Oblique" +ENDPROPERTIES +CHARS 192 +STARTCHAR defaultchar +ENCODING 0 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 9 9 1 0 +BITMAP +AA80 +0000 +8080 +0000 +8080 +0000 +8080 +0000 +AA80 +ENDCHAR +STARTCHAR space +ENCODING 32 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 5 9 1 0 +BITMAP +18 +18 +30 +30 +60 +40 +00 +C0 +C0 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 474 0 +DWIDTH 6 0 +BBX 7 3 2 6 +BITMAP +36 +6C +D8 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 8 1 0 +BITMAP +14 +14 +7E +28 +28 +FC +50 +50 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 1 -1 +BITMAP +08 +3C +6E +70 +38 +1C +2C +EC +78 +40 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 889 0 +DWIDTH 13 0 +BBX 11 9 2 0 +BITMAP +70C0 +D980 +DB00 +7600 +0600 +0DC0 +1B60 +3360 +61C0 +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 9 1 0 +BITMAP +1C +36 +36 +1C +39 +6F +C6 +CE +7B +ENDCHAR +STARTCHAR quotesingle +ENCODING 39 +SWIDTH 238 0 +DWIDTH 4 0 +BBX 4 3 2 6 +BITMAP +30 +60 +C0 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 6 12 0 -3 +BITMAP +0C +18 +30 +30 +60 +60 +C0 +C0 +C0 +60 +60 +30 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 6 12 0 -3 +BITMAP +30 +18 +18 +0C +0C +0C +18 +18 +30 +30 +60 +C0 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 389 0 +DWIDTH 6 0 +BBX 4 4 3 5 +BITMAP +50 +60 +F0 +40 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 584 0 +DWIDTH 8 0 +BBX 7 5 1 1 +BITMAP +18 +18 +FE +30 +30 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 4 0 -2 +BITMAP +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR hyphen +ENCODING 45 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 1 3 +BITMAP +F0 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 2 0 0 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 7 9 0 0 +BITMAP +02 +06 +0C +18 +10 +30 +60 +C0 +80 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +3C +66 +66 +46 +C6 +C4 +CC +CC +78 +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 2 0 +BITMAP +18 +F8 +30 +60 +60 +60 +C0 +C0 +C0 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +3C +66 +06 +0C +18 +30 +60 +C0 +F8 +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +3C +66 +06 +06 +3C +0C +0C +CC +78 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +06 +0E +16 +26 +4C +CC +FE +18 +18 +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +1E +30 +60 +78 +0C +0C +0C +D8 +70 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +1C +36 +60 +78 +EC +CC +C4 +CC +78 +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +7E +06 +0C +0C +18 +30 +30 +60 +C0 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +3C +66 +66 +2C +78 +CC +CC +DC +78 +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +3C +66 +46 +66 +6E +3C +0C +D8 +70 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 7 1 0 +BITMAP +30 +30 +00 +00 +00 +C0 +C0 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 9 1 -2 +BITMAP +30 +30 +00 +00 +00 +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 5 2 1 +BITMAP +1C +70 +C0 +60 +30 +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 3 1 2 +BITMAP +7C +00 +F8 +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 5 1 1 +BITMAP +30 +18 +0C +38 +E0 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 6 9 3 0 +BITMAP +78 +CC +9C +38 +60 +40 +00 +C0 +C0 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 975 0 +DWIDTH 11 0 +BBX 11 10 1 -1 +BITMAP +0F80 +3040 +6020 +46A0 +8920 +9120 +9240 +4D80 +6000 +1E00 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +06 +0E +0B +1B +33 +3F +63 +C3 +C3 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 9 1 0 +BITMAP +1F00 +1980 +3180 +3300 +7E00 +6300 +6300 +C600 +FC00 +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 9 1 0 +BITMAP +1E +33 +63 +60 +C0 +C0 +C6 +CC +78 +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 9 1 0 +BITMAP +1F00 +1980 +3180 +3180 +6180 +6300 +6300 +C600 +FC00 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 9 1 0 +BITMAP +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 9 1 0 +BITMAP +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +C000 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 9 1 0 +BITMAP +0F00 +3980 +3180 +6000 +6700 +C300 +C600 +CE00 +7A00 +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 9 1 0 +BITMAP +18C0 +18C0 +3180 +3180 +7F00 +6300 +6300 +C600 +C600 +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 5 9 1 0 +BITMAP +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 9 9 0 0 +BITMAP +0180 +0180 +0300 +0300 +0600 +0600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 10 9 1 0 +BITMAP +18C0 +1980 +3300 +3600 +3C00 +6600 +6600 +C300 +C300 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +18 +18 +30 +30 +60 +60 +60 +C0 +FC +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 833 0 +DWIDTH 12 0 +BBX 12 9 1 0 +BITMAP +1830 +1870 +38E0 +38E0 +6940 +6AC0 +6EC0 +CD80 +C980 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 9 1 0 +BITMAP +18C0 +18C0 +3980 +2980 +6980 +6500 +6700 +C600 +C600 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 9 1 0 +BITMAP +0F00 +3980 +3180 +6180 +6300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 9 1 0 +BITMAP +1F00 +1980 +3180 +3300 +7E00 +6000 +6000 +C000 +C000 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 9 1 0 +BITMAP +0F00 +3980 +3180 +6180 +6300 +C300 +DE00 +CE00 +7B00 +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 9 1 0 +BITMAP +1F00 +1980 +3180 +3300 +7E00 +6300 +6300 +C600 +C600 +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 9 1 0 +BITMAP +1E +33 +63 +70 +3C +0E +C6 +CC +78 +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 2 0 +BITMAP +FF +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 9 1 0 +BITMAP +3180 +3180 +6300 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 8 9 3 0 +BITMAP +C3 +C3 +C6 +C6 +CC +CC +58 +70 +60 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 9 2 0 +BITMAP +CCC0 +CCC0 +CD80 +DD80 +DD00 +ED00 +EE00 +4400 +4400 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 10 9 1 0 +BITMAP +30C0 +3180 +1B00 +1E00 +0C00 +1E00 +3600 +6300 +C300 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 7 9 2 0 +BITMAP +C6 +C6 +6C +6C +38 +30 +30 +60 +60 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 9 0 0 +BITMAP +3F80 +0300 +0600 +0C00 +1800 +3000 +6000 +C000 +FE00 +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 8 12 -1 -3 +BITMAP +0F +0C +18 +18 +30 +30 +30 +60 +60 +60 +C0 +F0 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 3 9 2 0 +BITMAP +C0 +C0 +C0 +40 +40 +40 +60 +60 +60 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 8 12 -2 -3 +BITMAP +0F +03 +06 +06 +0C +0C +0C +18 +18 +18 +30 +F0 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 6 1 3 +BITMAP +18 +38 +6C +6C +CC +CC +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 1 -1 -3 +BITMAP +FE +ENDCHAR +STARTCHAR grave +ENCODING 96 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 3 7 +BITMAP +C0 +60 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 7 0 0 +BITMAP +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +18 +18 +36 +3B +63 +66 +C6 +CC +F8 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +1E +33 +60 +60 +C6 +CC +78 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 9 0 0 +BITMAP +0180 +0180 +1B00 +3700 +6300 +6600 +C600 +CC00 +7C00 +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 7 9 1 0 +BITMAP +0E +18 +7C +30 +30 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 10 -1 -3 +BITMAP +0E80 +1B80 +3180 +3300 +6300 +6600 +3E00 +0600 +CC00 +7800 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +18 +18 +36 +3B +63 +66 +66 +CC +CC +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 9 0 0 +BITMAP +18 +00 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 7 12 -2 -3 +BITMAP +06 +00 +0C +0C +18 +18 +18 +30 +30 +30 +60 +C0 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +18 +18 +33 +36 +7C +78 +6C +CC +C6 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 9 0 0 +BITMAP +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 12 7 0 0 +BITMAP +2EE0 +3330 +3330 +6660 +6660 +CCC0 +CCC0 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +36 +3B +63 +66 +66 +CC +CC +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 10 -1 -3 +BITMAP +1B00 +1D80 +3180 +3300 +6300 +6600 +7C00 +6000 +C000 +C000 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 -3 +BITMAP +1D +37 +63 +66 +C6 +CC +7C +0C +18 +18 +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 7 7 0 0 +BITMAP +36 +3C +70 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +1E +33 +38 +1C +0C +CC +78 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 6 9 1 0 +BITMAP +18 +18 +7C +30 +60 +60 +60 +C0 +E0 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 2 0 +BITMAP +CC +CC +D8 +D8 +F0 +60 +40 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 7 1 0 +BITMAP +CCC0 +CCC0 +DD80 +DD80 +5500 +7700 +6600 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +33 +36 +1C +18 +38 +6C +CC +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 1 -3 +BITMAP +CC +CC +CC +D8 +50 +70 +60 +60 +C0 +80 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 7 7 0 0 +BITMAP +3E +06 +0C +38 +60 +C0 +F8 +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 7 12 1 -3 +BITMAP +0E +18 +30 +30 +60 +C0 +60 +60 +60 +C0 +C0 +70 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 280 0 +DWIDTH 4 0 +BBX 5 12 0 -3 +BITMAP +18 +18 +18 +10 +30 +30 +20 +60 +60 +40 +C0 +C0 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 7 12 -1 -3 +BITMAP +1C +06 +06 +0C +0C +06 +0C +18 +18 +18 +30 +E0 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 2 1 3 +BITMAP +74 +B8 +ENDCHAR +STARTCHAR space +ENCODING 160 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclamdown +ENCODING 161 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 5 10 -1 -3 +BITMAP +18 +18 +00 +10 +30 +30 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR cent +ENCODING 162 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 -1 +BITMAP +04 +3C +6E +D0 +D0 +E6 +EC +78 +40 +ENDCHAR +STARTCHAR sterling +ENCODING 163 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +0E +19 +10 +7C +30 +30 +60 +E6 +DC +ENDCHAR +STARTCHAR currency +ENCODING 164 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 6 0 1 +BITMAP +33 +1E +34 +2C +78 +CC +ENDCHAR +STARTCHAR yen +ENCODING 165 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +66 +66 +6C +38 +FC +30 +F8 +60 +60 +ENDCHAR +STARTCHAR brokenbar +ENCODING 166 +SWIDTH 280 0 +DWIDTH 4 0 +BBX 6 11 0 -2 +BITMAP +0C +0C +18 +18 +00 +00 +60 +60 +40 +C0 +C0 +ENDCHAR +STARTCHAR section +ENCODING 167 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 12 0 -3 +BITMAP +0E +1B +19 +38 +6C +66 +66 +36 +1C +98 +D8 +70 +ENDCHAR +STARTCHAR dieresis +ENCODING 168 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 1 3 8 +BITMAP +D8 +ENDCHAR +STARTCHAR copyright +ENCODING 169 +SWIDTH 737 0 +DWIDTH 11 0 +BBX 10 9 1 0 +BITMAP +1F00 +2080 +4E40 +5140 +A040 +A280 +9C80 +4100 +3E00 +ENDCHAR +STARTCHAR ordfeminine +ENCODING 170 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 5 6 2 3 +BITMAP +38 +08 +78 +50 +00 +F0 +ENDCHAR +STARTCHAR guillemotleft +ENCODING 171 +SWIDTH 556 0 +DWIDTH 10 0 +BBX 9 5 1 1 +BITMAP +1980 +7700 +CC00 +6600 +3300 +ENDCHAR +STARTCHAR logicalnot +ENCODING 172 +SWIDTH 584 0 +DWIDTH 8 0 +BBX 6 4 2 1 +BITMAP +FC +04 +08 +08 +ENDCHAR +STARTCHAR hyphen +ENCODING 173 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 1 3 +BITMAP +F0 +ENDCHAR +STARTCHAR registered +ENCODING 174 +SWIDTH 737 0 +DWIDTH 11 0 +BBX 10 9 1 0 +BITMAP +1F00 +2080 +4E40 +4A40 +9C40 +9480 +9280 +4100 +3E00 +ENDCHAR +STARTCHAR macron +ENCODING 175 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 1 3 8 +BITMAP +F0 +ENDCHAR +STARTCHAR degree +ENCODING 176 +SWIDTH 400 0 +DWIDTH 5 0 +BBX 4 4 2 4 +BITMAP +60 +90 +90 +60 +ENDCHAR +STARTCHAR plusminus +ENCODING 177 +SWIDTH 584 0 +DWIDTH 8 0 +BBX 8 7 0 0 +BITMAP +0C +0C +7F +18 +18 +00 +FE +ENDCHAR +STARTCHAR twosuperior +ENCODING 178 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 5 1 4 +BITMAP +60 +B0 +20 +40 +F0 +ENDCHAR +STARTCHAR threesuperior +ENCODING 179 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 5 1 4 +BITMAP +70 +30 +60 +30 +E0 +ENDCHAR +STARTCHAR acute +ENCODING 180 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 3 7 +BITMAP +60 +C0 +ENDCHAR +STARTCHAR mu +ENCODING 181 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 10 10 -2 -3 +BITMAP +0CC0 +0CC0 +18C0 +1980 +3180 +3300 +6D00 +6000 +C000 +C000 +ENDCHAR +STARTCHAR paragraph +ENCODING 182 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 12 2 -3 +BITMAP +3E +74 +F4 +F4 +E8 +E8 +68 +50 +50 +A0 +A0 +A0 +ENDCHAR +STARTCHAR periodcentered +ENCODING 183 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 2 2 3 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR cedilla +ENCODING 184 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 4 0 -3 +BITMAP +60 +30 +90 +E0 +ENDCHAR +STARTCHAR onesuperior +ENCODING 185 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 5 1 4 +BITMAP +20 +E0 +20 +40 +40 +ENDCHAR +STARTCHAR ordmasculine +ENCODING 186 +SWIDTH 365 0 +DWIDTH 6 0 +BBX 5 6 2 3 +BITMAP +38 +68 +58 +70 +00 +F0 +ENDCHAR +STARTCHAR guillemotright +ENCODING 187 +SWIDTH 556 0 +DWIDTH 10 0 +BBX 9 5 1 1 +BITMAP +6600 +3300 +1980 +7700 +CC00 +ENDCHAR +STARTCHAR onequarter +ENCODING 188 +SWIDTH 834 0 +DWIDTH 10 0 +BBX 9 9 2 0 +BITMAP +2000 +E300 +2600 +4C00 +5900 +1300 +3500 +6F80 +C200 +ENDCHAR +STARTCHAR onehalf +ENCODING 189 +SWIDTH 834 0 +DWIDTH 10 0 +BBX 9 9 1 0 +BITMAP +2000 +E300 +2600 +4C00 +5B00 +1580 +3100 +6200 +C780 +ENDCHAR +STARTCHAR threequarters +ENCODING 190 +SWIDTH 834 0 +DWIDTH 10 0 +BBX 10 9 1 0 +BITMAP +7000 +3180 +6300 +3600 +EC80 +0980 +1A80 +37C0 +6100 +ENDCHAR +STARTCHAR questiondown +ENCODING 191 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 -2 +BITMAP +0C +0C +00 +08 +18 +70 +E4 +CC +78 +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +0C +06 +00 +06 +06 +0F +1B +33 +3F +63 +C3 +C3 +ENDCHAR +STARTCHAR Aacute +ENCODING 193 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +03 +06 +00 +06 +06 +0F +1B +33 +3F +63 +C3 +C3 +ENDCHAR +STARTCHAR Acircumflex +ENCODING 194 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 12 0 0 +BITMAP +0700 +0D80 +0000 +0600 +0600 +0F00 +1B00 +3300 +3F00 +6300 +C300 +C300 +ENDCHAR +STARTCHAR Atilde +ENCODING 195 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 12 0 0 +BITMAP +0680 +0B00 +0000 +0600 +0600 +0F00 +1B00 +3300 +3F00 +6300 +C300 +C300 +ENDCHAR +STARTCHAR Adieresis +ENCODING 196 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 11 0 0 +BITMAP +0D80 +0000 +0600 +0600 +0F00 +1B00 +3300 +3F00 +6300 +C300 +C300 +ENDCHAR +STARTCHAR Aring +ENCODING 197 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 12 0 0 +BITMAP +0300 +0480 +0300 +0300 +0700 +0F00 +1B00 +3300 +3F00 +6300 +C300 +C300 +ENDCHAR +STARTCHAR AE +ENCODING 198 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 14 9 0 0 +BITMAP +07FC +0DC0 +0980 +1980 +33F0 +3F00 +6300 +C600 +C7E0 +ENDCHAR +STARTCHAR Ccedilla +ENCODING 199 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 1 -3 +BITMAP +1E +33 +63 +60 +C0 +C0 +C6 +CC +78 +30 +90 +E0 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 12 1 0 +BITMAP +0C00 +0600 +0000 +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR Eacute +ENCODING 201 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 12 1 0 +BITMAP +0300 +0600 +0000 +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR Ecircumflex +ENCODING 202 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 12 1 0 +BITMAP +0700 +0D80 +0000 +1F80 +1000 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR Edieresis +ENCODING 203 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 11 1 0 +BITMAP +0D80 +0000 +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR Igrave +ENCODING 204 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 5 12 1 0 +BITMAP +30 +18 +00 +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR Iacute +ENCODING 205 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 7 12 1 0 +BITMAP +06 +0C +00 +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR Icircumflex +ENCODING 206 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 7 12 1 0 +BITMAP +1C +36 +00 +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR Idieresis +ENCODING 207 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 7 11 1 0 +BITMAP +36 +00 +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR Eth +ENCODING 208 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 9 1 0 +BITMAP +1F00 +1980 +3180 +3180 +F980 +6300 +6300 +C600 +FC00 +ENDCHAR +STARTCHAR Ntilde +ENCODING 209 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 12 1 0 +BITMAP +0340 +0580 +0000 +18C0 +18C0 +38C0 +3980 +6980 +6500 +6700 +C600 +C600 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 12 1 0 +BITMAP +0600 +0300 +0000 +0F00 +3980 +3180 +6180 +C300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR Oacute +ENCODING 211 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 12 1 0 +BITMAP +0180 +0300 +0000 +0F00 +3980 +3180 +6180 +C300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR Ocircumflex +ENCODING 212 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 12 1 0 +BITMAP +0700 +0D80 +0000 +0F00 +3980 +3180 +6180 +C300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR Otilde +ENCODING 213 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 12 1 0 +BITMAP +0680 +0B00 +0000 +0F00 +3980 +3180 +6180 +C300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR Odieresis +ENCODING 214 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 11 1 0 +BITMAP +0D80 +0000 +0F00 +3980 +3180 +6180 +C300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR multiply +ENCODING 215 +SWIDTH 584 0 +DWIDTH 8 0 +BBX 7 5 1 1 +BITMAP +66 +3C +38 +78 +CC +ENDCHAR +STARTCHAR Oslash +ENCODING 216 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 11 9 0 0 +BITMAP +07A0 +1CC0 +19C0 +32C0 +3580 +6980 +7300 +6700 +BC00 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 12 1 0 +BITMAP +0C00 +0600 +0000 +3180 +3180 +3180 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR Uacute +ENCODING 218 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 12 1 0 +BITMAP +0300 +0600 +0000 +3180 +3180 +3180 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR Ucircumflex +ENCODING 219 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 12 1 0 +BITMAP +0700 +0D80 +0000 +3180 +3180 +3180 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR Udieresis +ENCODING 220 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 11 1 0 +BITMAP +1B00 +0000 +3180 +3180 +3180 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR Yacute +ENCODING 221 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 7 12 2 0 +BITMAP +0C +18 +00 +C6 +C6 +C6 +6C +6C +38 +30 +60 +60 +ENDCHAR +STARTCHAR Thorn +ENCODING 222 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 9 1 0 +BITMAP +18 +18 +3E +33 +23 +66 +7C +C0 +C0 +ENDCHAR +STARTCHAR germandbls +ENCODING 223 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +0E +1B +33 +36 +6C +66 +66 +CC +D8 +ENDCHAR +STARTCHAR agrave +ENCODING 224 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 10 0 0 +BITMAP +30 +18 +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR aacute +ENCODING 225 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 10 0 0 +BITMAP +06 +0C +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR acircumflex +ENCODING 226 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 10 0 0 +BITMAP +1C +36 +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR atilde +ENCODING 227 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 10 0 0 +BITMAP +1A +2C +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR adieresis +ENCODING 228 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 9 0 0 +BITMAP +36 +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR aring +ENCODING 229 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 10 0 0 +BITMAP +0C +12 +0C +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR ae +ENCODING 230 +SWIDTH 889 0 +DWIDTH 10 0 +BBX 11 7 0 0 +BITMAP +3BC0 +6660 +0460 +7FC0 +CC00 +9980 +EF00 +ENDCHAR +STARTCHAR ccedilla +ENCODING 231 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 10 0 -3 +BITMAP +1E +33 +60 +60 +C6 +CC +78 +30 +90 +E0 +ENDCHAR +STARTCHAR egrave +ENCODING 232 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +18 +0C +00 +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR eacute +ENCODING 233 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +06 +0C +00 +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR ecircumflex +ENCODING 234 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +0E +1B +00 +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR edieresis +ENCODING 235 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +1B +00 +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR igrave +ENCODING 236 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 10 0 0 +BITMAP +60 +30 +00 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR iacute +ENCODING 237 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 10 0 0 +BITMAP +18 +30 +00 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR icircumflex +ENCODING 238 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 6 10 0 0 +BITMAP +38 +6C +00 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR idieresis +ENCODING 239 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 6 9 0 0 +BITMAP +6C +00 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR eth +ENCODING 240 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +32 +1C +26 +1F +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR ntilde +ENCODING 241 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +0D +16 +00 +36 +3B +63 +66 +66 +CC +CC +ENDCHAR +STARTCHAR ograve +ENCODING 242 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +18 +0C +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR oacute +ENCODING 243 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +06 +0C +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR ocircumflex +ENCODING 244 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +0E +1B +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR otilde +ENCODING 245 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +0D +16 +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR odieresis +ENCODING 246 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +1B +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR divide +ENCODING 247 +SWIDTH 584 0 +DWIDTH 8 0 +BBX 7 5 1 1 +BITMAP +18 +00 +FE +00 +30 +ENDCHAR +STARTCHAR oslash +ENCODING 248 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 8 -1 0 +BITMAP +0080 +0F00 +1B80 +3580 +3B00 +7300 +6600 +BC00 +ENDCHAR +STARTCHAR ugrave +ENCODING 249 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +18 +0C +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR uacute +ENCODING 250 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +06 +0C +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR ucircumflex +ENCODING 251 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +0E +1B +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR udieresis +ENCODING 252 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +1B +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR yacute +ENCODING 253 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 13 1 -3 +BITMAP +18 +30 +00 +CC +CC +D8 +D8 +50 +70 +60 +60 +C0 +80 +ENDCHAR +STARTCHAR thorn +ENCODING 254 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 12 -1 -3 +BITMAP +0C00 +0C00 +1B00 +1D80 +1180 +3300 +3300 +6600 +7C00 +6000 +C000 +C000 +ENDCHAR +STARTCHAR ydieresis +ENCODING 255 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 12 1 -3 +BITMAP +6C +00 +CC +CC +D8 +D8 +50 +70 +60 +60 +C0 +80 +ENDCHAR +ENDFONT diff --git a/gui/themes/fonts/helvBO12.bdf b/gui/themes/fonts/helvBO12.bdf new file mode 100644 index 0000000000..728796dc26 --- /dev/null +++ b/gui/themes/fonts/helvBO12.bdf @@ -0,0 +1,12195 @@ +STARTFONT 2.1 +FONT -Adobe-Helvetica-Bold-O-Normal--12-120-75-75-P-69-ISO10646-1 +SIZE 12 75 75 +FONTBOUNDINGBOX 17 20 -2 -5 +COMMENT $Xorg: $ +COMMENT ISO10646-1 extension by Markus Kuhn <mkuhn@acm.org>, 2001-03-20 +COMMENT +COMMENT + +COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated. +COMMENT Copyright 1988, 1994 Digital Equipment Corporation. +COMMENT +COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be +COMMENT registered in certain jurisdictions. +COMMENT Permission to use these trademarks is hereby granted only in +COMMENT association with the images described in this file. +COMMENT +COMMENT Permission to use, copy, modify, distribute and sell this software +COMMENT and its documentation for any purpose and without fee is hereby +COMMENT granted, provided that the above copyright notices appear in all +COMMENT copies and that both those copyright notices and this permission +COMMENT notice appear in supporting documentation, and that the names of +COMMENT Adobe Systems and Digital Equipment Corporation not be used in +COMMENT advertising or publicity pertaining to distribution of the software +COMMENT without specific, written prior permission. Adobe Systems and +COMMENT Digital Equipment Corporation make no representations about the +COMMENT suitability of this software for any purpose. It is provided "as +COMMENT is" without express or implied warranty. +COMMENT - +STARTPROPERTIES 26 +FOUNDRY "Adobe" +FAMILY_NAME "Helvetica" +WEIGHT_NAME "Bold" +SLANT "O" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 12 +POINT_SIZE 120 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "P" +AVERAGE_WIDTH 69 +CHARSET_REGISTRY "ISO10646" +CHARSET_ENCODING "1" +CAP_HEIGHT 9 +X_HEIGHT 7 +FONT_ASCENT 11 +FONT_DESCENT 3 +FACE_NAME "Helvetica Bold Oblique" +COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved." +NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. " +_DEC_DEVICE_FONTNAMES "PS=Helvetica-BoldOblique" +DEFAULT_CHAR 0 +RELATIVE_SETWIDTH 50 +RELATIVE_WEIGHT 70 +FULL_NAME "Helvetica Bold Oblique" +ENDPROPERTIES +CHARS 723 +STARTCHAR char0 +ENCODING 0 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 9 9 1 0 +BITMAP +AA80 +0000 +8080 +0000 +8080 +0000 +8080 +0000 +AA80 +ENDCHAR +STARTCHAR space +ENCODING 32 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 5 9 1 0 +BITMAP +18 +18 +30 +30 +60 +40 +00 +C0 +C0 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 474 0 +DWIDTH 6 0 +BBX 7 3 2 6 +BITMAP +36 +6C +D8 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 8 1 0 +BITMAP +14 +14 +7E +28 +28 +FC +50 +50 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 1 -1 +BITMAP +08 +3C +6E +70 +38 +1C +2C +EC +78 +40 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 889 0 +DWIDTH 13 0 +BBX 11 9 2 0 +BITMAP +70C0 +D980 +DB00 +7600 +0600 +0DC0 +1B60 +3360 +61C0 +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 9 1 0 +BITMAP +1C +36 +36 +1C +39 +6F +C6 +CE +7B +ENDCHAR +STARTCHAR quotesingle +ENCODING 39 +SWIDTH 238 0 +DWIDTH 4 0 +BBX 4 3 2 6 +BITMAP +30 +60 +C0 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 6 12 0 -3 +BITMAP +0C +18 +30 +30 +60 +60 +C0 +C0 +C0 +60 +60 +30 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 6 12 0 -3 +BITMAP +30 +18 +18 +0C +0C +0C +18 +18 +30 +30 +60 +C0 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 389 0 +DWIDTH 6 0 +BBX 4 4 3 5 +BITMAP +50 +60 +F0 +40 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 584 0 +DWIDTH 8 0 +BBX 7 5 1 1 +BITMAP +18 +18 +FE +30 +30 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 4 0 -2 +BITMAP +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR hyphen +ENCODING 45 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 1 3 +BITMAP +F0 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 2 0 0 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 7 9 0 0 +BITMAP +02 +06 +0C +18 +10 +30 +60 +C0 +80 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +3C +66 +66 +46 +C6 +C4 +CC +CC +78 +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 2 0 +BITMAP +18 +F8 +30 +60 +60 +60 +C0 +C0 +C0 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +3C +66 +06 +0C +18 +30 +60 +C0 +F8 +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +3C +66 +06 +06 +3C +0C +0C +CC +78 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +06 +0E +16 +26 +4C +CC +FE +18 +18 +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +1E +30 +60 +78 +0C +0C +0C +D8 +70 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +1C +36 +60 +78 +EC +CC +C4 +CC +78 +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +7E +06 +0C +0C +18 +30 +30 +60 +C0 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +3C +66 +66 +2C +78 +CC +CC +DC +78 +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +3C +66 +46 +66 +6E +3C +0C +D8 +70 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 7 1 0 +BITMAP +30 +30 +00 +00 +00 +C0 +C0 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 9 1 -2 +BITMAP +30 +30 +00 +00 +00 +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 5 2 1 +BITMAP +1C +70 +C0 +60 +30 +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 3 1 2 +BITMAP +7C +00 +F8 +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 5 1 1 +BITMAP +30 +18 +0C +38 +E0 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 6 9 3 0 +BITMAP +78 +CC +9C +38 +60 +40 +00 +C0 +C0 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 975 0 +DWIDTH 11 0 +BBX 11 10 1 -1 +BITMAP +0F80 +3040 +6020 +46A0 +8920 +9120 +9240 +4D80 +6000 +1E00 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 9 0 0 +BITMAP +06 +0E +0B +1B +33 +3F +63 +C3 +C3 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 9 1 0 +BITMAP +1F00 +1980 +3180 +3300 +7E00 +6300 +6300 +C600 +FC00 +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 9 1 0 +BITMAP +1E +33 +63 +60 +C0 +C0 +C6 +CC +78 +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 9 1 0 +BITMAP +1F00 +1980 +3180 +3180 +6180 +6300 +6300 +C600 +FC00 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 9 1 0 +BITMAP +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 9 1 0 +BITMAP +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +C000 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 9 1 0 +BITMAP +0F00 +3980 +3180 +6000 +6700 +C300 +C600 +CE00 +7A00 +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 9 1 0 +BITMAP +18C0 +18C0 +3180 +3180 +7F00 +6300 +6300 +C600 +C600 +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 5 9 1 0 +BITMAP +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 9 9 0 0 +BITMAP +0180 +0180 +0300 +0300 +0600 +0600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 10 9 1 0 +BITMAP +18C0 +1980 +3300 +3600 +3C00 +6600 +6600 +C300 +C300 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +18 +18 +30 +30 +60 +60 +60 +C0 +FC +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 833 0 +DWIDTH 12 0 +BBX 12 9 1 0 +BITMAP +1830 +1870 +38E0 +38E0 +6940 +6AC0 +6EC0 +CD80 +C980 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 9 1 0 +BITMAP +18C0 +18C0 +3980 +2980 +6980 +6500 +6700 +C600 +C600 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 9 1 0 +BITMAP +0F00 +3980 +3180 +6180 +6300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 9 1 0 +BITMAP +1F00 +1980 +3180 +3300 +7E00 +6000 +6000 +C000 +C000 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 9 1 0 +BITMAP +0F00 +3980 +3180 +6180 +6300 +C300 +DE00 +CE00 +7B00 +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 9 1 0 +BITMAP +1F00 +1980 +3180 +3300 +7E00 +6300 +6300 +C600 +C600 +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 9 1 0 +BITMAP +1E +33 +63 +70 +3C +0E +C6 +CC +78 +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 2 0 +BITMAP +FF +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 9 1 0 +BITMAP +3180 +3180 +6300 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 8 9 3 0 +BITMAP +C3 +C3 +C6 +C6 +CC +CC +58 +70 +60 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 9 2 0 +BITMAP +CCC0 +CCC0 +CD80 +DD80 +DD00 +ED00 +EE00 +4400 +4400 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 10 9 1 0 +BITMAP +30C0 +3180 +1B00 +1E00 +0C00 +1E00 +3600 +6300 +C300 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 7 9 2 0 +BITMAP +C6 +C6 +6C +6C +38 +30 +30 +60 +60 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 9 0 0 +BITMAP +3F80 +0300 +0600 +0C00 +1800 +3000 +6000 +C000 +FE00 +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 8 12 -1 -3 +BITMAP +0F +0C +18 +18 +30 +30 +30 +60 +60 +60 +C0 +F0 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 3 9 2 0 +BITMAP +C0 +C0 +C0 +40 +40 +40 +60 +60 +60 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 8 12 -2 -3 +BITMAP +0F +03 +06 +06 +0C +0C +0C +18 +18 +18 +30 +F0 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 584 0 +DWIDTH 6 0 +BBX 6 6 1 3 +BITMAP +18 +38 +6C +6C +CC +CC +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 1 -1 -3 +BITMAP +FE +ENDCHAR +STARTCHAR grave +ENCODING 96 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 3 7 +BITMAP +C0 +60 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 7 0 0 +BITMAP +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +18 +18 +36 +3B +63 +66 +C6 +CC +F8 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +1E +33 +60 +60 +C6 +CC +78 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 9 0 0 +BITMAP +0180 +0180 +1B00 +3700 +6300 +6600 +C600 +CC00 +7C00 +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 7 9 1 0 +BITMAP +0E +18 +7C +30 +30 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 10 -1 -3 +BITMAP +0E80 +1B80 +3180 +3300 +6300 +6600 +3E00 +0600 +CC00 +7800 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +18 +18 +36 +3B +63 +66 +66 +CC +CC +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 9 0 0 +BITMAP +18 +00 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 7 12 -2 -3 +BITMAP +06 +00 +0C +0C +18 +18 +18 +30 +30 +30 +60 +C0 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +18 +18 +33 +36 +7C +78 +6C +CC +C6 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 9 0 0 +BITMAP +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 12 7 0 0 +BITMAP +2EE0 +3330 +3330 +6660 +6660 +CCC0 +CCC0 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +36 +3B +63 +66 +66 +CC +CC +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 10 -1 -3 +BITMAP +1B00 +1D80 +3180 +3300 +6300 +6600 +7C00 +6000 +C000 +C000 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 -3 +BITMAP +1D +37 +63 +66 +C6 +CC +7C +0C +18 +18 +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 7 7 0 0 +BITMAP +36 +3C +70 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +1E +33 +38 +1C +0C +CC +78 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 6 9 1 0 +BITMAP +18 +18 +7C +30 +60 +60 +60 +C0 +E0 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 2 0 +BITMAP +CC +CC +D8 +D8 +F0 +60 +40 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 7 1 0 +BITMAP +CCC0 +CCC0 +DD80 +DD80 +5500 +7700 +6600 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +33 +36 +1C +18 +38 +6C +CC +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 1 -3 +BITMAP +CC +CC +CC +D8 +50 +70 +60 +60 +C0 +80 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 7 7 0 0 +BITMAP +3E +06 +0C +38 +60 +C0 +F8 +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 7 12 1 -3 +BITMAP +0E +18 +30 +30 +60 +C0 +60 +60 +60 +C0 +C0 +70 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 280 0 +DWIDTH 4 0 +BBX 5 12 0 -3 +BITMAP +18 +18 +18 +10 +30 +30 +20 +60 +60 +40 +C0 +C0 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 7 12 -1 -3 +BITMAP +1C +06 +06 +0C +0C +06 +0C +18 +18 +18 +30 +E0 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 2 1 3 +BITMAP +74 +B8 +ENDCHAR +STARTCHAR space +ENCODING 160 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclamdown +ENCODING 161 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 5 10 -1 -3 +BITMAP +18 +18 +00 +10 +30 +30 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR cent +ENCODING 162 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 -1 +BITMAP +04 +3C +6E +D0 +D0 +E6 +EC +78 +40 +ENDCHAR +STARTCHAR sterling +ENCODING 163 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +0E +19 +10 +7C +30 +30 +60 +E6 +DC +ENDCHAR +STARTCHAR currency +ENCODING 164 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 6 0 1 +BITMAP +33 +1E +34 +2C +78 +CC +ENDCHAR +STARTCHAR yen +ENCODING 165 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +66 +66 +6C +38 +FC +30 +F8 +60 +60 +ENDCHAR +STARTCHAR brokenbar +ENCODING 166 +SWIDTH 280 0 +DWIDTH 4 0 +BBX 6 11 0 -2 +BITMAP +0C +0C +18 +18 +00 +00 +60 +60 +40 +C0 +C0 +ENDCHAR +STARTCHAR section +ENCODING 167 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 12 0 -3 +BITMAP +0E +1B +19 +38 +6C +66 +66 +36 +1C +98 +D8 +70 +ENDCHAR +STARTCHAR dieresis +ENCODING 168 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 1 3 8 +BITMAP +D8 +ENDCHAR +STARTCHAR copyright +ENCODING 169 +SWIDTH 737 0 +DWIDTH 11 0 +BBX 10 9 1 0 +BITMAP +1F00 +2080 +4E40 +5140 +A040 +A280 +9C80 +4100 +3E00 +ENDCHAR +STARTCHAR ordfeminine +ENCODING 170 +SWIDTH 370 0 +DWIDTH 6 0 +BBX 5 6 2 3 +BITMAP +38 +08 +78 +50 +00 +F0 +ENDCHAR +STARTCHAR guillemotleft +ENCODING 171 +SWIDTH 556 0 +DWIDTH 10 0 +BBX 9 5 1 1 +BITMAP +1980 +7700 +CC00 +6600 +3300 +ENDCHAR +STARTCHAR logicalnot +ENCODING 172 +SWIDTH 584 0 +DWIDTH 8 0 +BBX 6 4 2 1 +BITMAP +FC +04 +08 +08 +ENDCHAR +STARTCHAR hyphen +ENCODING 173 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 1 3 +BITMAP +F0 +ENDCHAR +STARTCHAR registered +ENCODING 174 +SWIDTH 737 0 +DWIDTH 11 0 +BBX 10 9 1 0 +BITMAP +1F00 +2080 +4E40 +4A40 +9C40 +9480 +9280 +4100 +3E00 +ENDCHAR +STARTCHAR macron +ENCODING 175 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 1 3 8 +BITMAP +F0 +ENDCHAR +STARTCHAR degree +ENCODING 176 +SWIDTH 400 0 +DWIDTH 5 0 +BBX 4 4 2 4 +BITMAP +60 +90 +90 +60 +ENDCHAR +STARTCHAR plusminus +ENCODING 177 +SWIDTH 584 0 +DWIDTH 8 0 +BBX 8 7 0 0 +BITMAP +0C +0C +7F +18 +18 +00 +FE +ENDCHAR +STARTCHAR twosuperior +ENCODING 178 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 5 1 4 +BITMAP +60 +B0 +20 +40 +F0 +ENDCHAR +STARTCHAR threesuperior +ENCODING 179 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 5 1 4 +BITMAP +70 +30 +60 +30 +E0 +ENDCHAR +STARTCHAR acute +ENCODING 180 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 3 7 +BITMAP +60 +C0 +ENDCHAR +STARTCHAR mu +ENCODING 181 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 10 10 -2 -3 +BITMAP +0CC0 +0CC0 +18C0 +1980 +3180 +3300 +6D00 +6000 +C000 +C000 +ENDCHAR +STARTCHAR paragraph +ENCODING 182 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 12 2 -3 +BITMAP +3E +74 +F4 +F4 +E8 +E8 +68 +50 +50 +A0 +A0 +A0 +ENDCHAR +STARTCHAR periodcentered +ENCODING 183 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 2 2 3 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR cedilla +ENCODING 184 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 4 0 -3 +BITMAP +60 +30 +90 +E0 +ENDCHAR +STARTCHAR onesuperior +ENCODING 185 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 5 1 4 +BITMAP +20 +E0 +20 +40 +40 +ENDCHAR +STARTCHAR ordmasculine +ENCODING 186 +SWIDTH 365 0 +DWIDTH 6 0 +BBX 5 6 2 3 +BITMAP +38 +68 +58 +70 +00 +F0 +ENDCHAR +STARTCHAR guillemotright +ENCODING 187 +SWIDTH 556 0 +DWIDTH 10 0 +BBX 9 5 1 1 +BITMAP +6600 +3300 +1980 +7700 +CC00 +ENDCHAR +STARTCHAR onequarter +ENCODING 188 +SWIDTH 834 0 +DWIDTH 10 0 +BBX 9 9 2 0 +BITMAP +2000 +E300 +2600 +4C00 +5900 +1300 +3500 +6F80 +C200 +ENDCHAR +STARTCHAR onehalf +ENCODING 189 +SWIDTH 834 0 +DWIDTH 10 0 +BBX 9 9 1 0 +BITMAP +2000 +E300 +2600 +4C00 +5B00 +1580 +3100 +6200 +C780 +ENDCHAR +STARTCHAR threequarters +ENCODING 190 +SWIDTH 834 0 +DWIDTH 10 0 +BBX 10 9 1 0 +BITMAP +7000 +3180 +6300 +3600 +EC80 +0980 +1A80 +37C0 +6100 +ENDCHAR +STARTCHAR questiondown +ENCODING 191 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 0 -2 +BITMAP +0C +0C +00 +08 +18 +70 +E4 +CC +78 +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +0C +06 +00 +06 +06 +0F +1B +33 +3F +63 +C3 +C3 +ENDCHAR +STARTCHAR Aacute +ENCODING 193 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +03 +06 +00 +06 +06 +0F +1B +33 +3F +63 +C3 +C3 +ENDCHAR +STARTCHAR Acircumflex +ENCODING 194 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 12 0 0 +BITMAP +0700 +0D80 +0000 +0600 +0600 +0F00 +1B00 +3300 +3F00 +6300 +C300 +C300 +ENDCHAR +STARTCHAR Atilde +ENCODING 195 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 12 0 0 +BITMAP +0680 +0B00 +0000 +0600 +0600 +0F00 +1B00 +3300 +3F00 +6300 +C300 +C300 +ENDCHAR +STARTCHAR Adieresis +ENCODING 196 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 11 0 0 +BITMAP +0D80 +0000 +0600 +0600 +0F00 +1B00 +3300 +3F00 +6300 +C300 +C300 +ENDCHAR +STARTCHAR Aring +ENCODING 197 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 12 0 0 +BITMAP +0300 +0480 +0300 +0300 +0700 +0F00 +1B00 +3300 +3F00 +6300 +C300 +C300 +ENDCHAR +STARTCHAR AE +ENCODING 198 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 14 9 0 0 +BITMAP +07FC +0DC0 +0980 +1980 +33F0 +3F00 +6300 +C600 +C7E0 +ENDCHAR +STARTCHAR Ccedilla +ENCODING 199 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 1 -3 +BITMAP +1E +33 +63 +60 +C0 +C0 +C6 +CC +78 +30 +90 +E0 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 12 1 0 +BITMAP +0C00 +0600 +0000 +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR Eacute +ENCODING 201 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 12 1 0 +BITMAP +0300 +0600 +0000 +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR Ecircumflex +ENCODING 202 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 12 1 0 +BITMAP +0700 +0D80 +0000 +1F80 +1000 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR Edieresis +ENCODING 203 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 11 1 0 +BITMAP +0D80 +0000 +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR Igrave +ENCODING 204 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 5 12 1 0 +BITMAP +30 +18 +00 +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR Iacute +ENCODING 205 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 7 12 1 0 +BITMAP +06 +0C +00 +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR Icircumflex +ENCODING 206 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 7 12 1 0 +BITMAP +1C +36 +00 +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR Idieresis +ENCODING 207 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 7 11 1 0 +BITMAP +36 +00 +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR Eth +ENCODING 208 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 9 1 0 +BITMAP +1F00 +1980 +3180 +3180 +F980 +6300 +6300 +C600 +FC00 +ENDCHAR +STARTCHAR Ntilde +ENCODING 209 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 12 1 0 +BITMAP +0340 +0580 +0000 +18C0 +18C0 +38C0 +3980 +6980 +6500 +6700 +C600 +C600 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 12 1 0 +BITMAP +0600 +0300 +0000 +0F00 +3980 +3180 +6180 +C300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR Oacute +ENCODING 211 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 12 1 0 +BITMAP +0180 +0300 +0000 +0F00 +3980 +3180 +6180 +C300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR Ocircumflex +ENCODING 212 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 12 1 0 +BITMAP +0700 +0D80 +0000 +0F00 +3980 +3180 +6180 +C300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR Otilde +ENCODING 213 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 12 1 0 +BITMAP +0680 +0B00 +0000 +0F00 +3980 +3180 +6180 +C300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR Odieresis +ENCODING 214 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 11 1 0 +BITMAP +0D80 +0000 +0F00 +3980 +3180 +6180 +C300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR multiply +ENCODING 215 +SWIDTH 584 0 +DWIDTH 8 0 +BBX 7 5 1 1 +BITMAP +66 +3C +38 +78 +CC +ENDCHAR +STARTCHAR Oslash +ENCODING 216 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 11 9 0 0 +BITMAP +07A0 +1CC0 +19C0 +32C0 +3580 +6980 +7300 +6700 +BC00 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 12 1 0 +BITMAP +0C00 +0600 +0000 +3180 +3180 +3180 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR Uacute +ENCODING 218 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 12 1 0 +BITMAP +0300 +0600 +0000 +3180 +3180 +3180 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR Ucircumflex +ENCODING 219 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 12 1 0 +BITMAP +0700 +0D80 +0000 +3180 +3180 +3180 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR Udieresis +ENCODING 220 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 11 1 0 +BITMAP +1B00 +0000 +3180 +3180 +3180 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR Yacute +ENCODING 221 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 7 12 2 0 +BITMAP +0C +18 +00 +C6 +C6 +C6 +6C +6C +38 +30 +60 +60 +ENDCHAR +STARTCHAR Thorn +ENCODING 222 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 9 1 0 +BITMAP +18 +18 +3E +33 +23 +66 +7C +C0 +C0 +ENDCHAR +STARTCHAR germandbls +ENCODING 223 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +0E +1B +33 +36 +6C +66 +66 +CC +D8 +ENDCHAR +STARTCHAR agrave +ENCODING 224 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 10 0 0 +BITMAP +30 +18 +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR aacute +ENCODING 225 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 10 0 0 +BITMAP +06 +0C +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR acircumflex +ENCODING 226 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 10 0 0 +BITMAP +1C +36 +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR atilde +ENCODING 227 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 10 0 0 +BITMAP +1A +2C +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR adieresis +ENCODING 228 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 9 0 0 +BITMAP +36 +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR aring +ENCODING 229 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 10 0 0 +BITMAP +0C +12 +0C +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR ae +ENCODING 230 +SWIDTH 889 0 +DWIDTH 10 0 +BBX 11 7 0 0 +BITMAP +3BC0 +6660 +0460 +7FC0 +CC00 +9980 +EF00 +ENDCHAR +STARTCHAR ccedilla +ENCODING 231 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 10 0 -3 +BITMAP +1E +33 +60 +60 +C6 +CC +78 +30 +90 +E0 +ENDCHAR +STARTCHAR egrave +ENCODING 232 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +18 +0C +00 +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR eacute +ENCODING 233 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +06 +0C +00 +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR ecircumflex +ENCODING 234 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +0E +1B +00 +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR edieresis +ENCODING 235 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +1B +00 +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR igrave +ENCODING 236 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 10 0 0 +BITMAP +60 +30 +00 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR iacute +ENCODING 237 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 10 0 0 +BITMAP +18 +30 +00 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR icircumflex +ENCODING 238 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 6 10 0 0 +BITMAP +38 +6C +00 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR idieresis +ENCODING 239 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 6 9 0 0 +BITMAP +6C +00 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR eth +ENCODING 240 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +32 +1C +26 +1F +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR ntilde +ENCODING 241 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +0D +16 +00 +36 +3B +63 +66 +66 +CC +CC +ENDCHAR +STARTCHAR ograve +ENCODING 242 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +18 +0C +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR oacute +ENCODING 243 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +06 +0C +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR ocircumflex +ENCODING 244 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +0E +1B +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR otilde +ENCODING 245 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +0D +16 +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR odieresis +ENCODING 246 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +1B +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR divide +ENCODING 247 +SWIDTH 584 0 +DWIDTH 8 0 +BBX 7 5 1 1 +BITMAP +18 +00 +FE +00 +30 +ENDCHAR +STARTCHAR oslash +ENCODING 248 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 8 -1 0 +BITMAP +0080 +0F00 +1B80 +3580 +3B00 +7300 +6600 +BC00 +ENDCHAR +STARTCHAR ugrave +ENCODING 249 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +18 +0C +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR uacute +ENCODING 250 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +06 +0C +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR ucircumflex +ENCODING 251 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +0E +1B +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR udieresis +ENCODING 252 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +1B +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR yacute +ENCODING 253 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 13 1 -3 +BITMAP +18 +30 +00 +CC +CC +D8 +D8 +50 +70 +60 +60 +C0 +80 +ENDCHAR +STARTCHAR thorn +ENCODING 254 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 12 -1 -3 +BITMAP +0C00 +0C00 +1B00 +1D80 +1180 +3300 +3300 +6600 +7C00 +6000 +C000 +C000 +ENDCHAR +STARTCHAR ydieresis +ENCODING 255 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 12 1 -3 +BITMAP +6C +00 +CC +CC +D8 +D8 +50 +70 +60 +60 +C0 +80 +ENDCHAR +STARTCHAR Amacron +ENCODING 256 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 11 0 0 +BITMAP +1E +00 +06 +0E +0B +1B +33 +3F +63 +C3 +C3 +ENDCHAR +STARTCHAR amacron +ENCODING 257 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 9 0 0 +BITMAP +3C +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR Abreve +ENCODING 258 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 0 +BITMAP +1B +0E +00 +06 +0E +0B +1B +33 +3F +63 +C3 +C3 +ENDCHAR +STARTCHAR abreve +ENCODING 259 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 10 0 0 +BITMAP +6C +38 +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR Aogonek +ENCODING 260 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 0 -3 +BITMAP +06 +0E +0B +1B +33 +3F +63 +C3 +CF +18 +10 +1C +ENDCHAR +STARTCHAR aogonek +ENCODING 261 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 10 0 -3 +BITMAP +3C +66 +06 +7C +CC +98 +FC +30 +20 +38 +ENDCHAR +STARTCHAR Cacute +ENCODING 262 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 1 0 +BITMAP +0C +18 +00 +1E +33 +63 +60 +C0 +C0 +C6 +CC +78 +ENDCHAR +STARTCHAR cacute +ENCODING 263 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +06 +0C +00 +1E +33 +60 +60 +C6 +CC +78 +ENDCHAR +STARTCHAR Ccircumflex +ENCODING 264 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 13 1 0 +BITMAP +08 +1C +36 +00 +1E +33 +63 +60 +C0 +C0 +C6 +CC +78 +ENDCHAR +STARTCHAR ccircumflex +ENCODING 265 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 11 0 0 +BITMAP +08 +1C +36 +00 +1E +33 +60 +60 +C6 +CC +78 +ENDCHAR +STARTCHAR Cdotaccent +ENCODING 266 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 11 1 0 +BITMAP +0C +00 +1E +33 +63 +60 +C0 +C0 +C6 +CC +78 +ENDCHAR +STARTCHAR cdotaccent +ENCODING 267 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +0C +00 +1E +33 +60 +60 +C6 +CC +78 +ENDCHAR +STARTCHAR Ccaron +ENCODING 268 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 13 1 0 +BITMAP +36 +1C +08 +00 +1E +33 +63 +60 +C0 +C0 +C6 +CC +78 +ENDCHAR +STARTCHAR ccaron +ENCODING 269 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 11 0 0 +BITMAP +36 +1C +08 +00 +1E +33 +60 +60 +C6 +CC +78 +ENDCHAR +STARTCHAR Dcaron +ENCODING 270 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 13 1 0 +BITMAP +1B00 +0E00 +0400 +0000 +1F00 +1980 +3180 +3180 +6180 +6300 +6300 +C600 +FC00 +ENDCHAR +STARTCHAR dcaron +ENCODING 271 +SWIDTH 858 0 +DWIDTH 11 0 +BBX 13 9 0 0 +BITMAP +0198 +0198 +1B30 +3700 +6300 +6600 +C600 +CC00 +7C00 +ENDCHAR +STARTCHAR Dcroat +ENCODING 272 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 9 1 0 +BITMAP +1F00 +1980 +3180 +3180 +F980 +6300 +6300 +C600 +FC00 +ENDCHAR +STARTCHAR dcroat +ENCODING 273 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 9 0 0 +BITMAP +0180 +0F80 +1B00 +3700 +6300 +6600 +C600 +CC00 +7C00 +ENDCHAR +STARTCHAR Emacron +ENCODING 274 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 11 1 0 +BITMAP +1E00 +0000 +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR emacron +ENCODING 275 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +1E +00 +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR Ebreve +ENCODING 276 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 12 1 0 +BITMAP +3600 +1C00 +0000 +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR ebreve +ENCODING 277 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +36 +1C +00 +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR Edotaccent +ENCODING 278 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 11 1 0 +BITMAP +0C00 +0000 +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR edotaccent +ENCODING 279 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +0C +00 +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR Eogonek +ENCODING 280 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 12 1 -3 +BITMAP +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +3000 +2000 +3800 +ENDCHAR +STARTCHAR eogonek +ENCODING 281 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 10 0 -3 +BITMAP +1E +33 +63 +7E +C0 +CC +78 +30 +20 +38 +ENDCHAR +STARTCHAR Ecaron +ENCODING 282 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 13 1 0 +BITMAP +3600 +1C00 +0800 +0000 +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR ecaron +ENCODING 283 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 11 0 0 +BITMAP +36 +1C +08 +00 +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR Gcircumflex +ENCODING 284 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 13 1 0 +BITMAP +0400 +0E00 +1B00 +0000 +0F00 +3980 +3180 +6000 +6700 +C300 +C600 +CE00 +7A00 +ENDCHAR +STARTCHAR gcircumflex +ENCODING 285 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 14 -1 -3 +BITMAP +0400 +0E00 +1B00 +0000 +0E80 +1B80 +3180 +3300 +6300 +6600 +3E00 +0600 +CC00 +7800 +ENDCHAR +STARTCHAR Gbreve +ENCODING 286 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 12 1 0 +BITMAP +1B00 +0E00 +0000 +0F00 +3980 +3180 +6000 +6700 +C300 +C600 +CE00 +7A00 +ENDCHAR +STARTCHAR gbreve +ENCODING 287 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 13 -1 -3 +BITMAP +1B00 +0E00 +0000 +0E80 +1B80 +3180 +3300 +6300 +6600 +3E00 +0600 +CC00 +7800 +ENDCHAR +STARTCHAR Gdotaccent +ENCODING 288 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 11 1 0 +BITMAP +0C00 +0000 +0F00 +3980 +3180 +6000 +6700 +C300 +C600 +CE00 +7A00 +ENDCHAR +STARTCHAR gdotaccent +ENCODING 289 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 12 -1 -3 +BITMAP +0C00 +0000 +0E80 +1B80 +3180 +3300 +6300 +6600 +3E00 +0600 +CC00 +7800 +ENDCHAR +STARTCHAR Gcommaaccent +ENCODING 290 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 14 1 -5 +BITMAP +0F00 +3980 +3180 +6000 +6700 +C300 +C600 +CE00 +7A00 +0000 +1800 +1800 +0800 +1000 +ENDCHAR +STARTCHAR gcommaaccent +ENCODING 291 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 14 -1 -3 +BITMAP +0600 +0C00 +0C00 +0000 +0E80 +1B80 +3180 +3300 +6300 +6600 +3E00 +0600 +CC00 +7800 +ENDCHAR +STARTCHAR Hcircumflex +ENCODING 292 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 13 1 0 +BITMAP +0400 +0E00 +1B00 +0000 +18C0 +18C0 +3180 +3180 +7F00 +6300 +6300 +C600 +C600 +ENDCHAR +STARTCHAR hcircumflex +ENCODING 293 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 13 0 0 +BITMAP +08 +1C +36 +00 +18 +18 +36 +3B +63 +66 +66 +CC +CC +ENDCHAR +STARTCHAR Hbar +ENCODING 294 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 9 1 0 +BITMAP +18C0 +FFC0 +3180 +3180 +7F00 +6300 +6300 +C600 +C600 +ENDCHAR +STARTCHAR hbar +ENCODING 295 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +18 +F8 +36 +3B +63 +66 +66 +CC +CC +ENDCHAR +STARTCHAR Itilde +ENCODING 296 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 6 12 1 0 +BITMAP +34 +58 +00 +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR itilde +ENCODING 297 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 10 0 0 +BITMAP +68 +B0 +00 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR Imacron +ENCODING 298 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 5 11 1 0 +BITMAP +78 +00 +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR imacron +ENCODING 299 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 9 0 0 +BITMAP +78 +00 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR Ibreve +ENCODING 300 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 6 12 1 0 +BITMAP +6C +38 +00 +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR ibreve +ENCODING 301 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 10 0 0 +BITMAP +D8 +70 +00 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR Iogonek +ENCODING 302 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 5 12 1 -3 +BITMAP +18 +18 +30 +30 +60 +60 +60 +C0 +E0 +C0 +80 +E0 +ENDCHAR +STARTCHAR iogonek +ENCODING 303 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 12 0 -3 +BITMAP +18 +00 +30 +30 +60 +60 +60 +C0 +E0 +C0 +80 +E0 +ENDCHAR +STARTCHAR Idotaccent +ENCODING 304 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 5 11 1 0 +BITMAP +30 +00 +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR dotlessi +ENCODING 305 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 7 0 0 +BITMAP +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR IJ +ENCODING 306 +SWIDTH 820 0 +DWIDTH 12 0 +BBX 13 9 1 0 +BITMAP +1818 +1818 +3030 +3030 +6060 +6060 +6C60 +CCC0 +C780 +ENDCHAR +STARTCHAR ij +ENCODING 307 +SWIDTH 542 0 +DWIDTH 6 0 +BBX 8 12 0 -3 +BITMAP +1B +00 +36 +36 +6C +6C +6C +D8 +D8 +18 +30 +60 +ENDCHAR +STARTCHAR Jcircumflex +ENCODING 308 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 9 13 0 0 +BITMAP +0200 +0700 +0D80 +0000 +0180 +0180 +0300 +0300 +0600 +0600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR jcircumflex +ENCODING 309 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 7 14 -2 -3 +BITMAP +08 +1C +36 +00 +0C +0C +18 +18 +18 +30 +30 +30 +60 +C0 +ENDCHAR +STARTCHAR Kcommaaccent +ENCODING 310 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 10 14 1 -5 +BITMAP +18C0 +1980 +3300 +3600 +3C00 +6600 +6600 +C300 +C300 +0000 +1800 +1800 +0800 +1000 +ENDCHAR +STARTCHAR kcommaaccent +ENCODING 311 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 14 0 -5 +BITMAP +18 +18 +33 +36 +7C +78 +6C +CC +C6 +00 +18 +18 +08 +10 +ENDCHAR +STARTCHAR kgreenlandic +ENCODING 312 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +33 +36 +7C +78 +6C +CC +C6 +ENDCHAR +STARTCHAR Lacute +ENCODING 313 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 12 1 0 +BITMAP +18 +30 +00 +18 +18 +30 +30 +60 +60 +60 +C0 +FC +ENDCHAR +STARTCHAR lacute +ENCODING 314 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 12 0 0 +BITMAP +18 +30 +00 +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR Lcommaaccent +ENCODING 315 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 14 1 -5 +BITMAP +18 +18 +30 +30 +60 +60 +60 +C0 +FC +00 +30 +30 +10 +20 +ENDCHAR +STARTCHAR lcommaaccent +ENCODING 316 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 14 0 -5 +BITMAP +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +00 +60 +60 +20 +40 +ENDCHAR +STARTCHAR Lcaron +ENCODING 317 +SWIDTH 858 0 +DWIDTH 11 0 +BBX 12 9 1 0 +BITMAP +1830 +1830 +3060 +3000 +6000 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR lcaron +ENCODING 318 +SWIDTH 542 0 +DWIDTH 7 0 +BBX 9 9 0 0 +BITMAP +1980 +1980 +3300 +3000 +6000 +6000 +6000 +C000 +C000 +ENDCHAR +STARTCHAR Ldot +ENCODING 319 +SWIDTH 858 0 +DWIDTH 11 0 +BBX 10 9 1 0 +BITMAP +1800 +1800 +3000 +3000 +60C0 +60C0 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR ldot +ENCODING 320 +SWIDTH 542 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +18 +18 +30 +30 +66 +66 +60 +C0 +C0 +ENDCHAR +STARTCHAR Lslash +ENCODING 321 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +18 +18 +30 +38 +E0 +60 +60 +C0 +FC +ENDCHAR +STARTCHAR lslash +ENCODING 322 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 9 0 0 +BITMAP +18 +18 +30 +38 +E0 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR Nacute +ENCODING 323 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 12 1 0 +BITMAP +0300 +0600 +0000 +18C0 +18C0 +3980 +2980 +6980 +6500 +6700 +C600 +C600 +ENDCHAR +STARTCHAR nacute +ENCODING 324 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +0C +18 +00 +36 +3B +63 +66 +66 +CC +CC +ENDCHAR +STARTCHAR Ncommaaccent +ENCODING 325 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 14 1 -5 +BITMAP +18C0 +18C0 +3980 +2980 +6980 +6500 +6700 +C600 +C600 +0000 +1800 +1800 +0800 +1000 +ENDCHAR +STARTCHAR ncommaaccent +ENCODING 326 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 12 0 -5 +BITMAP +36 +3B +63 +66 +66 +CC +CC +00 +30 +30 +10 +20 +ENDCHAR +STARTCHAR Ncaron +ENCODING 327 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 13 1 0 +BITMAP +1B00 +0E00 +0400 +0000 +18C0 +18C0 +3980 +2980 +6980 +6500 +6700 +C600 +C600 +ENDCHAR +STARTCHAR ncaron +ENCODING 328 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 0 0 +BITMAP +36 +1C +08 +00 +36 +3B +63 +66 +66 +CC +CC +ENDCHAR +STARTCHAR napostrophe +ENCODING 329 +SWIDTH 875 0 +DWIDTH 11 0 +BBX 9 9 3 0 +BITMAP +6000 +6000 +DB00 +1D80 +3180 +3300 +3300 +6600 +6600 +ENDCHAR +STARTCHAR Eng +ENCODING 330 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 12 1 -3 +BITMAP +18C0 +18C0 +3980 +2980 +6980 +6500 +6700 +C600 +C600 +0600 +0C00 +1800 +ENDCHAR +STARTCHAR eng +ENCODING 331 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 -3 +BITMAP +36 +3B +63 +66 +66 +CC +CC +0C +18 +30 +ENDCHAR +STARTCHAR Omacron +ENCODING 332 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 11 1 0 +BITMAP +1E00 +0000 +0F00 +3980 +3180 +6180 +6300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR omacron +ENCODING 333 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +1E +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR Obreve +ENCODING 334 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 12 1 0 +BITMAP +1B00 +0E00 +0000 +0F00 +3980 +3180 +6180 +6300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR obreve +ENCODING 335 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +36 +1C +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR Ohungarumlaut +ENCODING 336 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 12 1 0 +BITMAP +0D80 +1B00 +0000 +0F00 +3980 +3180 +6180 +6300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR ohungarumlaut +ENCODING 337 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +1B +36 +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR OE +ENCODING 338 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 13 9 1 0 +BITMAP +0FF8 +3980 +3300 +6300 +67E0 +C600 +C600 +CC00 +7FC0 +ENDCHAR +STARTCHAR oe +ENCODING 339 +SWIDTH 944 0 +DWIDTH 11 0 +BBX 12 7 0 0 +BITMAP +1DE0 +3330 +6230 +67E0 +C600 +CCC0 +7F80 +ENDCHAR +STARTCHAR Racute +ENCODING 340 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 12 1 0 +BITMAP +0600 +0C00 +0000 +1F00 +1980 +3180 +3300 +7E00 +6300 +6300 +C600 +C600 +ENDCHAR +STARTCHAR racute +ENCODING 341 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 7 10 0 0 +BITMAP +0C +18 +00 +36 +3C +70 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR Rcommaaccent +ENCODING 342 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 14 1 -5 +BITMAP +1F00 +1980 +3180 +3300 +7E00 +6300 +6300 +C600 +C600 +0000 +1800 +1800 +0800 +1000 +ENDCHAR +STARTCHAR rcommaaccent +ENCODING 343 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 7 12 0 -5 +BITMAP +36 +3C +70 +60 +60 +C0 +C0 +00 +60 +60 +20 +40 +ENDCHAR +STARTCHAR Rcaron +ENCODING 344 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 13 1 0 +BITMAP +1B00 +0E00 +0400 +0000 +1F00 +1980 +3180 +3300 +7E00 +6300 +6300 +C600 +C600 +ENDCHAR +STARTCHAR rcaron +ENCODING 345 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 7 11 0 0 +BITMAP +36 +1C +08 +00 +36 +3C +70 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR Sacute +ENCODING 346 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 12 1 0 +BITMAP +0C +18 +00 +1E +33 +63 +70 +3C +0E +C6 +CC +78 +ENDCHAR +STARTCHAR sacute +ENCODING 347 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +06 +0C +00 +1E +33 +38 +1C +0C +CC +78 +ENDCHAR +STARTCHAR Scircumflex +ENCODING 348 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 13 1 0 +BITMAP +08 +1C +36 +00 +1E +33 +63 +70 +3C +0E +C6 +CC +78 +ENDCHAR +STARTCHAR scircumflex +ENCODING 349 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 11 0 0 +BITMAP +08 +1C +36 +00 +1E +33 +38 +1C +0C +CC +78 +ENDCHAR +STARTCHAR Scedilla +ENCODING 350 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 12 1 -3 +BITMAP +1E +33 +63 +70 +3C +0E +C6 +CC +78 +18 +48 +70 +ENDCHAR +STARTCHAR scedilla +ENCODING 351 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 10 0 -3 +BITMAP +1E +33 +38 +1C +0C +CC +78 +18 +48 +70 +ENDCHAR +STARTCHAR Scaron +ENCODING 352 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 10 1 0 +BITMAP +1B +0E +04 +1E +33 +31 +1C +86 +C6 +7C +ENDCHAR +STARTCHAR scaron +ENCODING 353 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +1B +0E +04 +1E +33 +38 +1C +0C +CC +78 +ENDCHAR +STARTCHAR Tcommaaccent +ENCODING 354 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 12 2 -3 +BITMAP +FF +18 +30 +30 +60 +60 +60 +C0 +E0 +30 +90 +E0 +ENDCHAR +STARTCHAR tcommaaccent +ENCODING 355 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 6 12 1 -3 +BITMAP +18 +18 +7C +30 +60 +60 +60 +C0 +E0 +30 +90 +E0 +ENDCHAR +STARTCHAR Tcaron +ENCODING 356 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 13 2 0 +BITMAP +6C +38 +10 +00 +FF +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR tcaron +ENCODING 357 +SWIDTH 594 0 +DWIDTH 9 0 +BBX 10 9 1 0 +BITMAP +18C0 +18C0 +7D80 +3000 +6000 +6000 +6000 +C000 +E000 +ENDCHAR +STARTCHAR Tbar +ENCODING 358 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 2 0 +BITMAP +FF +18 +30 +30 +7E +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR tbar +ENCODING 359 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 6 9 1 0 +BITMAP +18 +18 +7C +30 +60 +7C +60 +C0 +E0 +ENDCHAR +STARTCHAR Utilde +ENCODING 360 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 12 1 0 +BITMAP +0D00 +1600 +0000 +3180 +3180 +6300 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR utilde +ENCODING 361 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +1A +2C +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR Umacron +ENCODING 362 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 11 1 0 +BITMAP +1E00 +0000 +3180 +3180 +6300 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR umacron +ENCODING 363 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +1E +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR Ubreve +ENCODING 364 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 12 1 0 +BITMAP +3600 +1C00 +0000 +3180 +3180 +6300 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR ubreve +ENCODING 365 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +36 +1C +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR Uring +ENCODING 366 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 13 1 0 +BITMAP +1C00 +3600 +1C00 +0000 +3180 +3180 +6300 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR uring +ENCODING 367 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 0 0 +BITMAP +1C +36 +1C +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR Uhungarumlaut +ENCODING 368 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 12 1 0 +BITMAP +1B00 +3600 +0000 +3180 +3180 +6300 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR uhungarumlaut +ENCODING 369 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +1B +36 +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR Uogonek +ENCODING 370 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 12 1 -3 +BITMAP +3180 +3180 +6300 +6300 +6300 +C600 +C600 +CC00 +7800 +3000 +2000 +3800 +ENDCHAR +STARTCHAR uogonek +ENCODING 371 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 -3 +BITMAP +33 +33 +63 +66 +C6 +CC +7C +30 +20 +38 +ENDCHAR +STARTCHAR Wcircumflex +ENCODING 372 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 13 2 0 +BITMAP +0800 +1C00 +3600 +0000 +CCC0 +CCC0 +CD80 +DD80 +DD00 +ED00 +EE00 +4400 +4400 +ENDCHAR +STARTCHAR wcircumflex +ENCODING 373 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 11 1 0 +BITMAP +0400 +0E00 +1B00 +0000 +CCC0 +CCC0 +DD80 +DD80 +5500 +7700 +6600 +ENDCHAR +STARTCHAR Ycircumflex +ENCODING 374 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 7 13 2 0 +BITMAP +10 +38 +6C +00 +C6 +C6 +6C +6C +38 +30 +30 +60 +60 +ENDCHAR +STARTCHAR ycircumflex +ENCODING 375 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 14 1 -3 +BITMAP +10 +38 +6C +00 +CC +CC +CC +D8 +50 +70 +60 +60 +C0 +80 +ENDCHAR +STARTCHAR Ydieresis +ENCODING 376 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 9 3 0 +BITMAP +6C +00 +C6 +CC +D8 +70 +60 +C0 +C0 +ENDCHAR +STARTCHAR Zacute +ENCODING 377 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 12 0 0 +BITMAP +0600 +0C00 +0000 +3F80 +0300 +0600 +0C00 +1800 +3000 +6000 +C000 +FE00 +ENDCHAR +STARTCHAR zacute +ENCODING 378 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 7 10 0 0 +BITMAP +0C +18 +00 +3E +06 +0C +38 +60 +C0 +F8 +ENDCHAR +STARTCHAR Zdotaccent +ENCODING 379 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 11 0 0 +BITMAP +0C00 +0000 +3F80 +0300 +0600 +0C00 +1800 +3000 +6000 +C000 +FE00 +ENDCHAR +STARTCHAR zdotaccent +ENCODING 380 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 7 9 0 0 +BITMAP +18 +00 +3E +06 +0C +38 +60 +C0 +F8 +ENDCHAR +STARTCHAR Zcaron +ENCODING 381 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 10 0 0 +BITMAP +1B00 +0E00 +0400 +3F80 +0300 +0600 +1C00 +3000 +6000 +FE00 +ENDCHAR +STARTCHAR zcaron +ENCODING 382 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 7 10 0 0 +BITMAP +36 +1C +08 +3E +06 +0C +38 +60 +C0 +F8 +ENDCHAR +STARTCHAR uni0186 +ENCODING 390 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 9 1 0 +BITMAP +1E +33 +63 +03 +03 +06 +C6 +CC +78 +ENDCHAR +STARTCHAR uni0189 +ENCODING 393 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 9 1 0 +BITMAP +1F00 +1980 +3180 +3180 +F980 +6300 +6300 +C600 +FC00 +ENDCHAR +STARTCHAR uni018E +ENCODING 398 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 9 1 0 +BITMAP +1F80 +0180 +0300 +0300 +3F00 +0600 +0600 +0C00 +FC00 +ENDCHAR +STARTCHAR florin +ENCODING 402 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 11 0 -3 +BITMAP +0E +18 +18 +7C +30 +30 +30 +60 +60 +60 +C0 +ENDCHAR +STARTCHAR uni0197 +ENCODING 407 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 5 9 1 0 +BITMAP +18 +18 +30 +30 +F8 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR uni019A +ENCODING 410 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 9 0 0 +BITMAP +18 +18 +30 +30 +F8 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR uni019D +ENCODING 413 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 12 12 -1 -3 +BITMAP +0630 +0630 +0E60 +0A60 +1A60 +1940 +19C0 +3080 +3080 +3000 +6000 +C000 +ENDCHAR +STARTCHAR uni019F +ENCODING 415 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 9 1 0 +BITMAP +0F00 +3980 +3180 +6180 +FF80 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR Ohorn +ENCODING 416 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 11 9 1 0 +BITMAP +0F60 +39E0 +31C0 +6180 +6300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR ohorn +ENCODING 417 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 11 7 0 0 +BITMAP +1E60 +3360 +63C0 +6600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR Uhorn +ENCODING 431 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 11 9 1 0 +BITMAP +31E0 +31E0 +63C0 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR uhorn +ENCODING 432 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 11 7 0 0 +BITMAP +3360 +3360 +63C0 +6600 +C600 +CC00 +7400 +ENDCHAR +STARTCHAR uni01B5 +ENCODING 437 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 9 0 0 +BITMAP +3F80 +0300 +0600 +0C00 +3E00 +3000 +6000 +C000 +FE00 +ENDCHAR +STARTCHAR uni01B6 +ENCODING 438 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 7 7 0 0 +BITMAP +3E +06 +0C +7C +60 +C0 +F8 +ENDCHAR +STARTCHAR uni01BB +ENCODING 443 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +3C +66 +06 +0C +FE +30 +60 +C0 +F8 +ENDCHAR +STARTCHAR uni01BC +ENCODING 444 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 0 +BITMAP +1E +30 +60 +78 +0C +0C +0C +D8 +70 +ENDCHAR +STARTCHAR uni01C0 +ENCODING 448 +SWIDTH 280 0 +DWIDTH 4 0 +BBX 5 12 0 -3 +BITMAP +18 +18 +18 +10 +30 +30 +20 +60 +60 +40 +C0 +C0 +ENDCHAR +STARTCHAR uni01C2 +ENCODING 450 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 12 1 -2 +BITMAP +0C +0C +0C +08 +18 +7C +10 +F8 +30 +20 +60 +60 +ENDCHAR +STARTCHAR uni01C3 +ENCODING 451 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 5 9 1 0 +BITMAP +18 +18 +30 +30 +60 +40 +00 +C0 +C0 +ENDCHAR +STARTCHAR uni01CD +ENCODING 461 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 13 0 0 +BITMAP +1B +0E +04 +00 +06 +0E +0B +1B +33 +3F +63 +C3 +C3 +ENDCHAR +STARTCHAR uni01CE +ENCODING 462 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 11 0 0 +BITMAP +6C +38 +10 +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR uni01CF +ENCODING 463 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 6 13 1 0 +BITMAP +6C +38 +10 +00 +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR uni01D0 +ENCODING 464 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 11 0 0 +BITMAP +D8 +70 +20 +00 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR uni01D1 +ENCODING 465 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 13 1 0 +BITMAP +1B00 +0E00 +0400 +0000 +0F00 +3980 +3180 +6180 +6300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR uni01D2 +ENCODING 466 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 0 0 +BITMAP +36 +1C +08 +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR uni01D3 +ENCODING 467 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 13 1 0 +BITMAP +3600 +1C00 +0800 +0000 +3180 +3180 +6300 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR uni01D4 +ENCODING 468 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 0 0 +BITMAP +36 +1C +08 +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR uni01D5 +ENCODING 469 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 13 1 0 +BITMAP +1E00 +0000 +1B00 +0000 +3180 +3180 +3180 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR uni01D6 +ENCODING 470 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 0 0 +BITMAP +1E +00 +1B +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR uni01D7 +ENCODING 471 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 14 1 0 +BITMAP +0600 +0C00 +0000 +1B00 +0000 +3180 +3180 +3180 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR uni01D8 +ENCODING 472 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 12 0 0 +BITMAP +06 +0C +00 +1B +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR uni01D9 +ENCODING 473 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 15 1 0 +BITMAP +1B00 +0E00 +0400 +0000 +1B00 +0000 +3180 +3180 +3180 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR uni01DA +ENCODING 474 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 13 0 0 +BITMAP +36 +1C +08 +00 +1B +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR uni01DB +ENCODING 475 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 14 1 0 +BITMAP +1800 +0C00 +0000 +1B00 +0000 +3180 +3180 +3180 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR uni01DC +ENCODING 476 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 12 0 0 +BITMAP +18 +0C +00 +1B +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR uni01DD +ENCODING 477 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +1E +33 +03 +7E +C6 +CC +78 +ENDCHAR +STARTCHAR uni01DE +ENCODING 478 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 13 0 0 +BITMAP +0F00 +0000 +0D80 +0000 +0600 +0600 +0F00 +1B00 +3300 +3F00 +6300 +C300 +C300 +ENDCHAR +STARTCHAR uni01DF +ENCODING 479 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 11 0 0 +BITMAP +3C +00 +36 +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR uni01E0 +ENCODING 480 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 13 0 0 +BITMAP +1E +00 +0C +00 +06 +0E +0B +1B +33 +3F +63 +C3 +C3 +ENDCHAR +STARTCHAR uni01E1 +ENCODING 481 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 11 0 0 +BITMAP +3C +00 +18 +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR uni01E2 +ENCODING 482 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 14 11 0 0 +BITMAP +03C0 +0000 +07FC +0DC0 +0980 +1980 +33F0 +3F00 +6300 +C600 +C7E0 +ENDCHAR +STARTCHAR uni01E3 +ENCODING 483 +SWIDTH 889 0 +DWIDTH 10 0 +BBX 11 9 0 0 +BITMAP +0F00 +0000 +3BC0 +6660 +0460 +7FC0 +CC00 +9980 +EF00 +ENDCHAR +STARTCHAR uni01E4 +ENCODING 484 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 10 9 1 0 +BITMAP +0F00 +3980 +3180 +6000 +6700 +C7C0 +C600 +CE00 +7A00 +ENDCHAR +STARTCHAR uni01E5 +ENCODING 485 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 10 -1 -3 +BITMAP +0E80 +1B80 +3180 +3300 +6300 +6600 +3E00 +FF80 +CC00 +7800 +ENDCHAR +STARTCHAR Gcaron +ENCODING 486 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 13 1 0 +BITMAP +1B00 +0E00 +0400 +0000 +0F00 +3980 +3180 +6000 +6700 +C300 +C600 +CE00 +7A00 +ENDCHAR +STARTCHAR gcaron +ENCODING 487 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 14 -1 -3 +BITMAP +1B00 +0E00 +0400 +0000 +0E80 +1B80 +3180 +3300 +6300 +6600 +3E00 +0600 +CC00 +7800 +ENDCHAR +STARTCHAR uni01E8 +ENCODING 488 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 10 13 1 0 +BITMAP +1B00 +0E00 +0400 +0000 +18C0 +1980 +3300 +3600 +3C00 +6600 +6600 +C300 +C300 +ENDCHAR +STARTCHAR uni01E9 +ENCODING 489 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 13 0 0 +BITMAP +36 +1C +08 +00 +18 +18 +33 +36 +7C +78 +6C +CC +C6 +ENDCHAR +STARTCHAR uni01EA +ENCODING 490 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 12 1 -3 +BITMAP +0F00 +3980 +3180 +6180 +6300 +C300 +C600 +CE00 +7800 +3000 +2000 +3800 +ENDCHAR +STARTCHAR uni01EB +ENCODING 491 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 -3 +BITMAP +1E +33 +63 +66 +C6 +CC +78 +30 +20 +38 +ENDCHAR +STARTCHAR uni01EC +ENCODING 492 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 14 1 -3 +BITMAP +1E00 +0000 +0F00 +3980 +3180 +6180 +6300 +C300 +C600 +CE00 +7800 +3000 +2000 +3800 +ENDCHAR +STARTCHAR uni01ED +ENCODING 493 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 12 0 -3 +BITMAP +1E +00 +1E +33 +63 +66 +C6 +CC +78 +30 +20 +38 +ENDCHAR +STARTCHAR uni01F0 +ENCODING 496 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 7 14 -2 -3 +BITMAP +36 +1C +08 +00 +0C +0C +18 +18 +18 +30 +30 +30 +60 +C0 +ENDCHAR +STARTCHAR uni01F4 +ENCODING 500 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 12 1 0 +BITMAP +0600 +0C00 +0000 +0F00 +3980 +3180 +6000 +6700 +C300 +C600 +CE00 +7A00 +ENDCHAR +STARTCHAR uni01F5 +ENCODING 501 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 13 -1 -3 +BITMAP +0600 +0C00 +0000 +0E80 +1B80 +3180 +3300 +6300 +6600 +3E00 +0600 +CC00 +7800 +ENDCHAR +STARTCHAR uni01F8 +ENCODING 504 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 12 1 0 +BITMAP +0C00 +0600 +0000 +18C0 +18C0 +3980 +2980 +6980 +6500 +6700 +C600 +C600 +ENDCHAR +STARTCHAR uni01F9 +ENCODING 505 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +18 +0C +00 +36 +3B +63 +66 +66 +CC +CC +ENDCHAR +STARTCHAR Aringacute +ENCODING 506 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 15 0 0 +BITMAP +0300 +0600 +0000 +0300 +0480 +0300 +0300 +0700 +0F00 +1B00 +3300 +3F00 +6300 +C300 +C300 +ENDCHAR +STARTCHAR aringacute +ENCODING 507 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 13 0 0 +BITMAP +0C +18 +00 +0C +12 +0C +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR AEacute +ENCODING 508 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 14 12 0 0 +BITMAP +00C0 +0180 +0000 +07FC +0DC0 +0980 +1980 +33F0 +3F00 +6300 +C600 +C7E0 +ENDCHAR +STARTCHAR aeacute +ENCODING 509 +SWIDTH 889 0 +DWIDTH 10 0 +BBX 11 10 0 0 +BITMAP +0300 +0600 +0000 +3BC0 +6660 +0460 +7FC0 +CC00 +9980 +EF00 +ENDCHAR +STARTCHAR Oslashacute +ENCODING 510 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 11 12 0 0 +BITMAP +0300 +0600 +0000 +07A0 +1CC0 +19C0 +32C0 +3580 +6980 +7300 +6700 +BC00 +ENDCHAR +STARTCHAR oslashacute +ENCODING 511 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 11 -1 0 +BITMAP +0300 +0600 +0000 +0080 +0F00 +1B80 +3580 +3B00 +7300 +6600 +BC00 +ENDCHAR +STARTCHAR Scommaaccent +ENCODING 536 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 14 1 -5 +BITMAP +1E +33 +63 +70 +3C +0E +C6 +CC +78 +00 +30 +30 +10 +20 +ENDCHAR +STARTCHAR scommaaccent +ENCODING 537 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 12 0 -5 +BITMAP +1E +33 +38 +1C +0C +CC +78 +00 +30 +30 +10 +20 +ENDCHAR +STARTCHAR Tcommaaccent +ENCODING 538 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 14 2 -5 +BITMAP +FF +18 +30 +30 +60 +60 +60 +C0 +C0 +00 +60 +60 +20 +40 +ENDCHAR +STARTCHAR tcommaaccent +ENCODING 539 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 6 14 1 -5 +BITMAP +18 +18 +7C +30 +60 +60 +60 +C0 +E0 +00 +60 +60 +20 +40 +ENDCHAR +STARTCHAR uni021E +ENCODING 542 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 13 1 0 +BITMAP +1B00 +0E00 +0400 +0000 +18C0 +18C0 +3180 +3180 +7F00 +6300 +6300 +C600 +C600 +ENDCHAR +STARTCHAR uni021F +ENCODING 543 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 13 0 0 +BITMAP +36 +1C +08 +00 +18 +18 +36 +3B +63 +66 +66 +CC +CC +ENDCHAR +STARTCHAR uni0226 +ENCODING 550 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 11 0 0 +BITMAP +0C +00 +06 +0E +0B +1B +33 +3F +63 +C3 +C3 +ENDCHAR +STARTCHAR uni0227 +ENCODING 551 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 9 0 0 +BITMAP +18 +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR uni0228 +ENCODING 552 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 12 1 -3 +BITMAP +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +1800 +4800 +7000 +ENDCHAR +STARTCHAR uni0229 +ENCODING 553 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 10 0 -3 +BITMAP +1E +33 +63 +7E +C0 +CC +78 +18 +48 +70 +ENDCHAR +STARTCHAR uni022A +ENCODING 554 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 13 1 0 +BITMAP +0F00 +0000 +0D80 +0000 +0F00 +3980 +3180 +6180 +C300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR uni022B +ENCODING 555 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 0 0 +BITMAP +1E +00 +1B +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR uni022C +ENCODING 556 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 14 1 0 +BITMAP +0F00 +0000 +0680 +0B00 +0000 +0F00 +3980 +3180 +6180 +C300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR uni022D +ENCODING 557 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 12 0 0 +BITMAP +1E +00 +0D +16 +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR uni022E +ENCODING 558 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 11 1 0 +BITMAP +0C00 +0000 +0F00 +3980 +3180 +6180 +6300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR uni022F +ENCODING 559 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +0C +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR uni0230 +ENCODING 560 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 13 1 0 +BITMAP +1E00 +0000 +0C00 +0000 +0F00 +3980 +3180 +6180 +6300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR uni0231 +ENCODING 561 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 0 0 +BITMAP +1E +00 +0C +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR uni0232 +ENCODING 562 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 7 11 2 0 +BITMAP +3C +00 +C6 +C6 +6C +6C +38 +30 +30 +60 +60 +ENDCHAR +STARTCHAR uni0233 +ENCODING 563 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 12 1 -3 +BITMAP +78 +00 +CC +CC +CC +D8 +50 +70 +60 +60 +C0 +80 +ENDCHAR +STARTCHAR uni0250 +ENCODING 592 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 7 0 0 +BITMAP +6E +32 +66 +7C +C0 +CC +78 +ENDCHAR +STARTCHAR uni0259 +ENCODING 601 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +1E +33 +03 +7E +C6 +CC +78 +ENDCHAR +STARTCHAR uni025F +ENCODING 607 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 7 9 1 -2 +BITMAP +06 +06 +0C +0C +18 +18 +7C +30 +E0 +ENDCHAR +STARTCHAR uni0265 +ENCODING 613 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 -2 +BITMAP +33 +33 +66 +66 +C6 +DC +6C +18 +18 +ENDCHAR +STARTCHAR uni0275 +ENCODING 629 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +1E +33 +63 +FF +C6 +CC +78 +ENDCHAR +STARTCHAR uni0279 +ENCODING 633 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 7 7 0 0 +BITMAP +06 +06 +0C +0C +1C +78 +D8 +ENDCHAR +STARTCHAR uni0287 +ENCODING 647 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 6 9 1 0 +BITMAP +1C +0C +18 +18 +18 +30 +F8 +60 +60 +ENDCHAR +STARTCHAR uni0289 +ENCODING 649 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 7 0 0 +BITMAP +33 +33 +63 +FF +C6 +CC +74 +ENDCHAR +STARTCHAR uni028C +ENCODING 652 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 2 0 +BITMAP +08 +18 +3C +6C +6C +CC +CC +ENDCHAR +STARTCHAR uni028D +ENCODING 653 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 7 1 0 +BITMAP +1980 +3B80 +2A80 +6EC0 +6EC0 +CCC0 +CCC0 +ENDCHAR +STARTCHAR uni028E +ENCODING 654 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 1 0 +BITMAP +04 +0C +18 +18 +38 +28 +6C +CC +CC +CC +ENDCHAR +STARTCHAR uni029E +ENCODING 670 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 9 0 -2 +BITMAP +63 +33 +36 +1E +3E +6C +CC +18 +18 +ENDCHAR +STARTCHAR uni02BB +ENCODING 699 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 3 3 3 6 +BITMAP +60 +C0 +C0 +ENDCHAR +STARTCHAR afii57929 +ENCODING 700 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 3 3 3 6 +BITMAP +60 +60 +C0 +ENDCHAR +STARTCHAR afii64937 +ENCODING 701 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 3 3 3 6 +BITMAP +C0 +C0 +60 +ENDCHAR +STARTCHAR circumflex +ENCODING 710 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 3 2 7 +BITMAP +20 +70 +D8 +ENDCHAR +STARTCHAR caron +ENCODING 711 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 3 3 6 +BITMAP +D8 +70 +20 +ENDCHAR +STARTCHAR uni02C8 +ENCODING 712 +SWIDTH 238 0 +DWIDTH 4 0 +BBX 4 3 2 6 +BITMAP +30 +60 +C0 +ENDCHAR +STARTCHAR macron +ENCODING 713 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 1 3 8 +BITMAP +F0 +ENDCHAR +STARTCHAR uni02CA +ENCODING 714 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 3 7 +BITMAP +60 +C0 +ENDCHAR +STARTCHAR uni02CB +ENCODING 715 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 3 7 +BITMAP +C0 +60 +ENDCHAR +STARTCHAR uni02CD +ENCODING 717 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 1 3 -2 +BITMAP +F0 +ENDCHAR +STARTCHAR uni02CE +ENCODING 718 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 3 -3 +BITMAP +C0 +60 +ENDCHAR +STARTCHAR uni02CF +ENCODING 719 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 3 -3 +BITMAP +60 +C0 +ENDCHAR +STARTCHAR breve +ENCODING 728 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 5 2 2 7 +BITMAP +D8 +70 +ENDCHAR +STARTCHAR dotaccent +ENCODING 729 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 2 1 3 8 +BITMAP +C0 +ENDCHAR +STARTCHAR ring +ENCODING 730 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 3 2 6 +BITMAP +70 +D8 +70 +ENDCHAR +STARTCHAR ogonek +ENCODING 731 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 4 0 -3 +BITMAP +60 +C0 +80 +E0 +ENDCHAR +STARTCHAR tilde +ENCODING 732 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 2 3 7 +BITMAP +68 +B0 +ENDCHAR +STARTCHAR hungarumlaut +ENCODING 733 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 6 2 2 7 +BITMAP +6C +D8 +ENDCHAR +STARTCHAR uni02EE +ENCODING 750 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 6 3 2 6 +BITMAP +6C +6C +D8 +ENDCHAR +STARTCHAR uni037E +ENCODING 894 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 9 1 -2 +BITMAP +30 +30 +00 +00 +00 +C0 +C0 +40 +80 +ENDCHAR +STARTCHAR tonos +ENCODING 900 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 2 3 7 +BITMAP +60 +C0 +ENDCHAR +STARTCHAR dieresistonos +ENCODING 901 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 4 3 8 +BITMAP +30 +60 +00 +D8 +ENDCHAR +STARTCHAR anoteleia +ENCODING 903 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 2 2 3 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR mu +ENCODING 956 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 10 10 -2 -3 +BITMAP +0CC0 +0CC0 +18C0 +1980 +3180 +3300 +6D00 +6000 +C000 +C000 +ENDCHAR +STARTCHAR uni1E00 +ENCODING 7680 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 13 0 -4 +BITMAP +06 +0E +0B +1B +33 +3F +63 +C3 +C3 +00 +1C +36 +1C +ENDCHAR +STARTCHAR uni1E01 +ENCODING 7681 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 11 0 -4 +BITMAP +3C +66 +06 +7C +CC +98 +EC +00 +38 +6C +38 +ENDCHAR +STARTCHAR uni1E02 +ENCODING 7682 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 11 1 0 +BITMAP +0C00 +0000 +1F00 +1980 +3180 +3300 +7E00 +6300 +6300 +C600 +FC00 +ENDCHAR +STARTCHAR uni1E03 +ENCODING 7683 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 0 0 +BITMAP +18 +00 +18 +18 +36 +3B +63 +66 +C6 +CC +F8 +ENDCHAR +STARTCHAR uni1E04 +ENCODING 7684 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 11 1 -2 +BITMAP +1F00 +1980 +3180 +3300 +7E00 +6300 +6300 +C600 +FC00 +0000 +1800 +ENDCHAR +STARTCHAR uni1E05 +ENCODING 7685 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 0 -2 +BITMAP +18 +18 +36 +3B +63 +66 +C6 +CC +F8 +00 +30 +ENDCHAR +STARTCHAR uni1E06 +ENCODING 7686 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 11 1 -2 +BITMAP +1F00 +1980 +3180 +3300 +7E00 +6300 +6300 +C600 +FC00 +0000 +3C00 +ENDCHAR +STARTCHAR uni1E07 +ENCODING 7687 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 0 -2 +BITMAP +18 +18 +36 +3B +63 +66 +C6 +CC +F8 +00 +78 +ENDCHAR +STARTCHAR uni1E08 +ENCODING 7688 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 15 1 -3 +BITMAP +0C +18 +00 +1E +33 +63 +60 +C0 +C0 +C6 +CC +78 +30 +90 +E0 +ENDCHAR +STARTCHAR uni1E09 +ENCODING 7689 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 13 0 -3 +BITMAP +0C +18 +00 +1E +33 +60 +60 +C6 +CC +78 +30 +90 +E0 +ENDCHAR +STARTCHAR uni1E0A +ENCODING 7690 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 11 1 0 +BITMAP +0C00 +0000 +1F00 +1980 +3180 +3180 +6180 +6300 +6300 +C600 +FC00 +ENDCHAR +STARTCHAR uni1E0B +ENCODING 7691 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 11 0 0 +BITMAP +0600 +0000 +0180 +0180 +1B00 +3700 +6300 +6600 +C600 +CC00 +7C00 +ENDCHAR +STARTCHAR uni1E0C +ENCODING 7692 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 11 1 -2 +BITMAP +1F00 +1980 +3180 +3180 +6180 +6300 +6300 +C600 +FC00 +0000 +1800 +ENDCHAR +STARTCHAR uni1E0D +ENCODING 7693 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 11 0 -2 +BITMAP +0180 +0180 +1B00 +3700 +6300 +6600 +C600 +CC00 +7C00 +0000 +1800 +ENDCHAR +STARTCHAR uni1E0E +ENCODING 7694 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 11 1 -2 +BITMAP +1F00 +1980 +3180 +3180 +6180 +6300 +6300 +C600 +FC00 +0000 +3C00 +ENDCHAR +STARTCHAR uni1E0F +ENCODING 7695 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 11 0 -2 +BITMAP +0180 +0180 +1B00 +3700 +6300 +6600 +C600 +CC00 +7C00 +0000 +3C00 +ENDCHAR +STARTCHAR uni1E10 +ENCODING 7696 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 12 1 -3 +BITMAP +1F00 +1980 +3180 +3180 +6180 +6300 +6300 +C600 +FC00 +0C00 +2400 +3800 +ENDCHAR +STARTCHAR uni1E11 +ENCODING 7697 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 12 0 -3 +BITMAP +0180 +0180 +1B00 +3700 +6300 +6600 +C600 +CC00 +7C00 +1800 +4800 +7000 +ENDCHAR +STARTCHAR uni1E12 +ENCODING 7698 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 13 1 -4 +BITMAP +1F00 +1980 +3180 +3180 +6180 +6300 +6300 +C600 +FC00 +0000 +1000 +3800 +6C00 +ENDCHAR +STARTCHAR uni1E13 +ENCODING 7699 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 13 0 -4 +BITMAP +0180 +0180 +1B00 +3700 +6300 +6600 +C600 +CC00 +7C00 +0000 +1000 +3800 +6C00 +ENDCHAR +STARTCHAR uni1E14 +ENCODING 7700 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 14 1 0 +BITMAP +1800 +0C00 +0000 +1E00 +0000 +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR uni1E15 +ENCODING 7701 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 12 0 0 +BITMAP +18 +0C +00 +1E +00 +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR uni1E16 +ENCODING 7702 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 14 1 0 +BITMAP +0600 +0C00 +0000 +1E00 +0000 +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR uni1E17 +ENCODING 7703 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 12 0 0 +BITMAP +06 +0C +00 +1E +00 +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR uni1E18 +ENCODING 7704 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 13 1 -4 +BITMAP +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +0000 +1000 +3800 +6C00 +ENDCHAR +STARTCHAR uni1E19 +ENCODING 7705 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 11 0 -4 +BITMAP +1E +33 +63 +7E +C0 +CC +78 +00 +10 +38 +6C +ENDCHAR +STARTCHAR uni1E1A +ENCODING 7706 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 12 1 -3 +BITMAP +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +0000 +6800 +B000 +ENDCHAR +STARTCHAR uni1E1B +ENCODING 7707 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 10 0 -3 +BITMAP +1E +33 +63 +7E +C0 +CC +78 +00 +34 +58 +ENDCHAR +STARTCHAR uni1E1C +ENCODING 7708 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 15 1 -3 +BITMAP +3600 +1C00 +0000 +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +1800 +4800 +7000 +ENDCHAR +STARTCHAR uni1E1D +ENCODING 7709 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 13 0 -3 +BITMAP +36 +1C +00 +1E +33 +63 +7E +C0 +CC +78 +18 +48 +70 +ENDCHAR +STARTCHAR uni1E1E +ENCODING 7710 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 11 1 0 +BITMAP +0C00 +0000 +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +C000 +ENDCHAR +STARTCHAR uni1E1F +ENCODING 7711 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 7 11 1 0 +BITMAP +18 +00 +0E +18 +7C +30 +30 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR uni1E20 +ENCODING 7712 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 11 1 0 +BITMAP +1E00 +0000 +0F00 +3980 +3180 +6000 +6700 +C300 +C600 +CE00 +7A00 +ENDCHAR +STARTCHAR uni1E21 +ENCODING 7713 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 12 -1 -3 +BITMAP +1E00 +0000 +0E80 +1B80 +3180 +3300 +6300 +6600 +3E00 +0600 +CC00 +7800 +ENDCHAR +STARTCHAR uni1E22 +ENCODING 7714 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 11 1 0 +BITMAP +0600 +0000 +18C0 +18C0 +3180 +3180 +7F00 +6300 +6300 +C600 +C600 +ENDCHAR +STARTCHAR uni1E23 +ENCODING 7715 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 0 0 +BITMAP +18 +00 +18 +18 +36 +3B +63 +66 +66 +CC +CC +ENDCHAR +STARTCHAR uni1E24 +ENCODING 7716 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 11 1 -2 +BITMAP +18C0 +18C0 +3180 +3180 +7F00 +6300 +6300 +C600 +C600 +0000 +1800 +ENDCHAR +STARTCHAR uni1E25 +ENCODING 7717 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 0 -2 +BITMAP +18 +18 +36 +3B +63 +66 +66 +CC +CC +00 +18 +ENDCHAR +STARTCHAR uni1E26 +ENCODING 7718 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 11 1 0 +BITMAP +1B00 +0000 +18C0 +18C0 +3180 +3180 +7F00 +6300 +6300 +C600 +C600 +ENDCHAR +STARTCHAR uni1E27 +ENCODING 7719 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 0 0 +BITMAP +36 +00 +18 +18 +36 +3B +63 +66 +66 +CC +CC +ENDCHAR +STARTCHAR uni1E28 +ENCODING 7720 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 12 1 -3 +BITMAP +18C0 +18C0 +3180 +3180 +7F00 +6300 +6300 +C600 +DE00 +0C00 +2400 +3800 +ENDCHAR +STARTCHAR uni1E29 +ENCODING 7721 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 12 0 -3 +BITMAP +18 +18 +36 +3B +63 +66 +66 +CC +FC +18 +48 +70 +ENDCHAR +STARTCHAR uni1E2A +ENCODING 7722 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 12 1 -3 +BITMAP +18C0 +18C0 +3180 +3180 +7F00 +6300 +6300 +C600 +C600 +0000 +3600 +1C00 +ENDCHAR +STARTCHAR uni1E2B +ENCODING 7723 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 12 0 -3 +BITMAP +18 +18 +36 +3B +63 +66 +66 +CC +CC +00 +6C +38 +ENDCHAR +STARTCHAR uni1E2C +ENCODING 7724 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 6 12 0 -3 +BITMAP +0C +0C +18 +18 +30 +30 +30 +60 +60 +00 +68 +B0 +ENDCHAR +STARTCHAR uni1E2D +ENCODING 7725 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 6 12 -1 -3 +BITMAP +0C +00 +18 +18 +30 +30 +30 +60 +60 +00 +68 +B0 +ENDCHAR +STARTCHAR uni1E2E +ENCODING 7726 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 7 14 1 0 +BITMAP +0C +18 +00 +36 +00 +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR uni1E2F +ENCODING 7727 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 6 12 0 0 +BITMAP +18 +30 +00 +6C +00 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR uni1E30 +ENCODING 7728 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 10 12 1 0 +BITMAP +0600 +0C00 +0000 +18C0 +1980 +3300 +3600 +3C00 +6600 +6600 +C300 +C300 +ENDCHAR +STARTCHAR uni1E31 +ENCODING 7729 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 12 0 0 +BITMAP +0C +18 +00 +18 +18 +33 +36 +7C +78 +6C +CC +C6 +ENDCHAR +STARTCHAR uni1E32 +ENCODING 7730 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 10 11 1 -2 +BITMAP +18C0 +1980 +3300 +3600 +3C00 +6600 +6600 +C300 +C300 +0000 +1800 +ENDCHAR +STARTCHAR uni1E33 +ENCODING 7731 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 11 0 -2 +BITMAP +18 +18 +33 +36 +7C +78 +6C +CC +C6 +00 +18 +ENDCHAR +STARTCHAR uni1E34 +ENCODING 7732 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 10 11 1 -2 +BITMAP +18C0 +1980 +3300 +3600 +3C00 +6600 +6600 +C300 +C300 +0000 +3C00 +ENDCHAR +STARTCHAR uni1E35 +ENCODING 7733 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 11 0 -2 +BITMAP +18 +18 +33 +36 +7C +78 +6C +CC +C6 +00 +3C +ENDCHAR +STARTCHAR uni1E36 +ENCODING 7734 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 1 -2 +BITMAP +18 +18 +30 +30 +60 +60 +60 +C0 +FC +00 +30 +ENDCHAR +STARTCHAR uni1E37 +ENCODING 7735 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 11 0 -2 +BITMAP +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +00 +60 +ENDCHAR +STARTCHAR uni1E38 +ENCODING 7736 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 13 1 -2 +BITMAP +78 +00 +18 +18 +30 +30 +60 +60 +60 +C0 +FC +00 +30 +ENDCHAR +STARTCHAR uni1E39 +ENCODING 7737 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 13 0 -2 +BITMAP +78 +00 +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +00 +60 +ENDCHAR +STARTCHAR uni1E3A +ENCODING 7738 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 11 1 -2 +BITMAP +18 +18 +30 +30 +60 +60 +60 +C0 +FC +00 +78 +ENDCHAR +STARTCHAR uni1E3B +ENCODING 7739 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 11 0 -2 +BITMAP +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +00 +F0 +ENDCHAR +STARTCHAR uni1E3C +ENCODING 7740 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 6 13 1 -4 +BITMAP +18 +18 +30 +30 +60 +60 +60 +C0 +FC +00 +20 +70 +D8 +ENDCHAR +STARTCHAR uni1E3D +ENCODING 7741 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 6 13 -1 -4 +BITMAP +0C +0C +18 +18 +30 +30 +30 +60 +60 +00 +20 +70 +D8 +ENDCHAR +STARTCHAR uni1E3E +ENCODING 7742 +SWIDTH 833 0 +DWIDTH 12 0 +BBX 12 12 1 0 +BITMAP +0180 +0300 +0000 +1830 +1870 +38E0 +38E0 +6940 +6AC0 +6EC0 +CD80 +C980 +ENDCHAR +STARTCHAR uni1E3F +ENCODING 7743 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 12 10 0 0 +BITMAP +0300 +0600 +0000 +2EE0 +3330 +3330 +6660 +6660 +CCC0 +CCC0 +ENDCHAR +STARTCHAR uni1E40 +ENCODING 7744 +SWIDTH 833 0 +DWIDTH 12 0 +BBX 12 11 1 0 +BITMAP +0300 +0000 +1830 +1870 +38E0 +38E0 +6940 +6AC0 +6EC0 +CD80 +C980 +ENDCHAR +STARTCHAR uni1E41 +ENCODING 7745 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 12 9 0 0 +BITMAP +0300 +0000 +2EE0 +3330 +3330 +6660 +6660 +CCC0 +CCC0 +ENDCHAR +STARTCHAR uni1E42 +ENCODING 7746 +SWIDTH 833 0 +DWIDTH 12 0 +BBX 12 11 1 -2 +BITMAP +1830 +1870 +38E0 +38E0 +6940 +6AC0 +6EC0 +CD80 +C980 +0000 +0C00 +ENDCHAR +STARTCHAR uni1E43 +ENCODING 7747 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 12 9 0 -2 +BITMAP +2EE0 +3330 +3330 +6660 +6660 +CCC0 +CCC0 +0000 +0C00 +ENDCHAR +STARTCHAR uni1E44 +ENCODING 7748 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 11 1 0 +BITMAP +0600 +0000 +18C0 +18C0 +3980 +2980 +6980 +6500 +6700 +C600 +C600 +ENDCHAR +STARTCHAR uni1E45 +ENCODING 7749 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +18 +00 +36 +3B +63 +66 +66 +CC +CC +ENDCHAR +STARTCHAR uni1E46 +ENCODING 7750 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 11 1 -2 +BITMAP +18C0 +18C0 +3980 +2980 +6980 +6500 +6700 +C600 +C600 +0000 +1800 +ENDCHAR +STARTCHAR uni1E47 +ENCODING 7751 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 -2 +BITMAP +36 +3B +63 +66 +66 +CC +CC +00 +30 +ENDCHAR +STARTCHAR uni1E48 +ENCODING 7752 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 11 1 -2 +BITMAP +18C0 +18C0 +3980 +2980 +6980 +6500 +6700 +C600 +C600 +0000 +3C00 +ENDCHAR +STARTCHAR uni1E49 +ENCODING 7753 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 -2 +BITMAP +36 +3B +63 +66 +66 +CC +CC +00 +78 +ENDCHAR +STARTCHAR uni1E4A +ENCODING 7754 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 13 1 -4 +BITMAP +18C0 +18C0 +3980 +2980 +6980 +6500 +6700 +C600 +C600 +0000 +0800 +1C00 +3600 +ENDCHAR +STARTCHAR uni1E4B +ENCODING 7755 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 0 -4 +BITMAP +36 +3B +63 +66 +66 +CC +CC +00 +10 +38 +6C +ENDCHAR +STARTCHAR uni1E4C +ENCODING 7756 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 15 1 0 +BITMAP +0300 +0600 +0000 +0680 +0B00 +0000 +0F00 +3980 +3180 +6180 +C300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR uni1E4D +ENCODING 7757 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 13 0 0 +BITMAP +06 +0C +00 +0D +16 +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR uni1E4E +ENCODING 7758 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 14 1 0 +BITMAP +1B00 +0000 +0680 +0B00 +0000 +0F00 +3980 +3180 +6180 +C300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR uni1E4F +ENCODING 7759 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 12 0 0 +BITMAP +1B +00 +0D +16 +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR uni1E50 +ENCODING 7760 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 14 1 0 +BITMAP +1800 +0C00 +0000 +1E00 +0000 +0F00 +3980 +3180 +6180 +6300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR uni1E51 +ENCODING 7761 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 12 0 0 +BITMAP +18 +0C +00 +1E +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR uni1E52 +ENCODING 7762 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 14 1 0 +BITMAP +0600 +0C00 +0000 +1E00 +0000 +0F00 +3980 +3180 +6180 +6300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR uni1E53 +ENCODING 7763 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 12 0 0 +BITMAP +06 +0C +00 +1E +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR uni1E54 +ENCODING 7764 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 12 1 0 +BITMAP +0600 +0C00 +0000 +1F00 +1980 +3180 +3300 +7E00 +6000 +6000 +C000 +C000 +ENDCHAR +STARTCHAR uni1E55 +ENCODING 7765 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 13 -1 -3 +BITMAP +0600 +0C00 +0000 +1B00 +1D80 +3180 +3300 +6300 +6600 +7C00 +6000 +C000 +C000 +ENDCHAR +STARTCHAR uni1E56 +ENCODING 7766 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 11 1 0 +BITMAP +0C00 +0000 +1F00 +1980 +3180 +3300 +7E00 +6000 +6000 +C000 +C000 +ENDCHAR +STARTCHAR uni1E57 +ENCODING 7767 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 12 -1 -3 +BITMAP +0C00 +0000 +1B00 +1D80 +3180 +3300 +6300 +6600 +7C00 +6000 +C000 +C000 +ENDCHAR +STARTCHAR uni1E58 +ENCODING 7768 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 11 1 0 +BITMAP +0C00 +0000 +1F00 +1980 +3180 +3300 +7E00 +6300 +6300 +C600 +C600 +ENDCHAR +STARTCHAR uni1E59 +ENCODING 7769 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 7 9 0 0 +BITMAP +18 +00 +36 +3C +70 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR uni1E5A +ENCODING 7770 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 11 1 -2 +BITMAP +1F00 +1980 +3180 +3300 +7E00 +6300 +6300 +C600 +C600 +0000 +1800 +ENDCHAR +STARTCHAR uni1E5B +ENCODING 7771 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 7 9 0 -2 +BITMAP +36 +3C +70 +60 +60 +C0 +C0 +00 +60 +ENDCHAR +STARTCHAR uni1E5C +ENCODING 7772 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 13 1 -2 +BITMAP +1E00 +0000 +1F00 +1980 +3180 +3300 +7E00 +6300 +6300 +C600 +C600 +0000 +1800 +ENDCHAR +STARTCHAR uni1E5D +ENCODING 7773 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 7 11 0 -2 +BITMAP +3C +00 +36 +3C +70 +60 +60 +C0 +C0 +00 +60 +ENDCHAR +STARTCHAR uni1E5E +ENCODING 7774 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 11 1 -2 +BITMAP +1F00 +1980 +3180 +3300 +7E00 +6300 +6300 +C600 +C600 +0000 +3C00 +ENDCHAR +STARTCHAR uni1E5F +ENCODING 7775 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 7 9 0 -2 +BITMAP +36 +3C +70 +60 +60 +C0 +C0 +00 +F0 +ENDCHAR +STARTCHAR uni1E60 +ENCODING 7776 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 11 1 0 +BITMAP +0C +00 +1E +33 +63 +70 +3C +0E +C6 +CC +78 +ENDCHAR +STARTCHAR uni1E61 +ENCODING 7777 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +0C +00 +1E +33 +38 +1C +0C +CC +78 +ENDCHAR +STARTCHAR uni1E62 +ENCODING 7778 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 11 1 -2 +BITMAP +1E +33 +63 +70 +3C +0E +C6 +CC +78 +00 +30 +ENDCHAR +STARTCHAR uni1E63 +ENCODING 7779 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 9 0 -2 +BITMAP +1E +33 +38 +1C +0C +CC +78 +00 +30 +ENDCHAR +STARTCHAR uni1E64 +ENCODING 7780 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 14 1 0 +BITMAP +0C +00 +0C +18 +00 +1E +33 +63 +70 +3C +0E +C6 +CC +78 +ENDCHAR +STARTCHAR uni1E65 +ENCODING 7781 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 12 0 0 +BITMAP +0C +00 +06 +0C +00 +1E +33 +38 +1C +0C +CC +78 +ENDCHAR +STARTCHAR uni1E66 +ENCODING 7782 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 12 1 0 +BITMAP +0C +00 +1B +0E +04 +1E +33 +31 +1C +86 +C6 +7C +ENDCHAR +STARTCHAR uni1E67 +ENCODING 7783 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 12 0 0 +BITMAP +0C +00 +1B +0E +04 +1E +33 +38 +1C +0C +CC +78 +ENDCHAR +STARTCHAR uni1E68 +ENCODING 7784 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 8 13 1 -2 +BITMAP +0C +00 +1E +33 +63 +70 +3C +0E +C6 +CC +78 +00 +30 +ENDCHAR +STARTCHAR uni1E69 +ENCODING 7785 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 11 0 -2 +BITMAP +18 +00 +1E +33 +38 +1C +0C +CC +78 +00 +30 +ENDCHAR +STARTCHAR uni1E6A +ENCODING 7786 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 2 0 +BITMAP +18 +00 +FF +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR uni1E6B +ENCODING 7787 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 6 11 1 0 +BITMAP +30 +00 +18 +18 +7C +30 +60 +60 +60 +C0 +E0 +ENDCHAR +STARTCHAR uni1E6C +ENCODING 7788 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 2 -2 +BITMAP +FF +18 +30 +30 +60 +60 +60 +C0 +C0 +00 +60 +ENDCHAR +STARTCHAR uni1E6D +ENCODING 7789 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 6 11 1 -2 +BITMAP +18 +18 +7C +30 +60 +60 +60 +C0 +E0 +00 +60 +ENDCHAR +STARTCHAR uni1E6E +ENCODING 7790 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 2 -2 +BITMAP +FF +18 +30 +30 +60 +60 +60 +C0 +C0 +00 +F0 +ENDCHAR +STARTCHAR uni1E6F +ENCODING 7791 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 6 11 1 -2 +BITMAP +18 +18 +7C +30 +60 +60 +60 +C0 +E0 +00 +F0 +ENDCHAR +STARTCHAR uni1E70 +ENCODING 7792 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 13 2 -4 +BITMAP +FF +18 +30 +30 +60 +60 +60 +C0 +C0 +00 +20 +70 +D8 +ENDCHAR +STARTCHAR uni1E71 +ENCODING 7793 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 6 13 1 -4 +BITMAP +18 +18 +7C +30 +60 +60 +60 +C0 +E0 +00 +20 +70 +D8 +ENDCHAR +STARTCHAR uni1E72 +ENCODING 7794 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 11 1 -2 +BITMAP +3180 +3180 +6300 +6300 +6300 +C600 +C600 +CC00 +7800 +0000 +6C00 +ENDCHAR +STARTCHAR uni1E73 +ENCODING 7795 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 -2 +BITMAP +33 +33 +63 +66 +C6 +CC +74 +00 +6C +ENDCHAR +STARTCHAR uni1E74 +ENCODING 7796 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 12 1 -3 +BITMAP +3180 +3180 +6300 +6300 +6300 +C600 +C600 +CC00 +7800 +0000 +3400 +5800 +ENDCHAR +STARTCHAR uni1E75 +ENCODING 7797 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 10 0 -3 +BITMAP +33 +33 +63 +66 +C6 +CC +74 +00 +34 +58 +ENDCHAR +STARTCHAR uni1E76 +ENCODING 7798 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 13 1 -4 +BITMAP +3180 +3180 +6300 +6300 +6300 +C600 +C600 +CC00 +7800 +0000 +1000 +3800 +6C00 +ENDCHAR +STARTCHAR uni1E77 +ENCODING 7799 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 0 -4 +BITMAP +33 +33 +63 +66 +C6 +CC +74 +00 +10 +38 +6C +ENDCHAR +STARTCHAR uni1E78 +ENCODING 7800 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 15 1 0 +BITMAP +0600 +0C00 +0000 +0D00 +1600 +0000 +3180 +3180 +6300 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR uni1E79 +ENCODING 7801 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 13 0 0 +BITMAP +0C +18 +00 +1A +2C +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR uni1E7A +ENCODING 7802 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 13 1 0 +BITMAP +1B00 +0000 +1E00 +0000 +3180 +3180 +6300 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR uni1E7B +ENCODING 7803 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 0 0 +BITMAP +36 +00 +1E +00 +33 +33 +63 +66 +C6 +CC +74 +ENDCHAR +STARTCHAR uni1E7C +ENCODING 7804 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 8 12 3 0 +BITMAP +1A +2C +00 +C3 +C3 +C6 +C6 +CC +CC +58 +70 +60 +ENDCHAR +STARTCHAR uni1E7D +ENCODING 7805 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 2 0 +BITMAP +34 +58 +00 +CC +CC +D8 +D8 +F0 +60 +40 +ENDCHAR +STARTCHAR uni1E7E +ENCODING 7806 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 8 11 3 -2 +BITMAP +C3 +C3 +C6 +C6 +CC +CC +58 +70 +60 +00 +30 +ENDCHAR +STARTCHAR uni1E7F +ENCODING 7807 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 2 -2 +BITMAP +CC +CC +D8 +D8 +F0 +60 +40 +00 +60 +ENDCHAR +STARTCHAR Wgrave +ENCODING 7808 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 12 2 0 +BITMAP +1800 +0C00 +0000 +CCC0 +CCC0 +CD80 +DD80 +DD00 +ED00 +EE00 +4400 +4400 +ENDCHAR +STARTCHAR wgrave +ENCODING 7809 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 10 1 0 +BITMAP +1800 +0C00 +0000 +CCC0 +CCC0 +DD80 +DD80 +5500 +7700 +6600 +ENDCHAR +STARTCHAR Wacute +ENCODING 7810 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 12 2 0 +BITMAP +0600 +0C00 +0000 +CCC0 +CCC0 +CD80 +DD80 +DD00 +ED00 +EE00 +4400 +4400 +ENDCHAR +STARTCHAR wacute +ENCODING 7811 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 10 1 0 +BITMAP +0600 +0C00 +0000 +CCC0 +CCC0 +DD80 +DD80 +5500 +7700 +6600 +ENDCHAR +STARTCHAR Wdieresis +ENCODING 7812 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 11 2 0 +BITMAP +3600 +0000 +CCC0 +CCC0 +CD80 +DD80 +DD00 +ED00 +EE00 +4400 +4400 +ENDCHAR +STARTCHAR wdieresis +ENCODING 7813 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 9 1 0 +BITMAP +1B00 +0000 +CCC0 +CCC0 +DD80 +DD80 +5500 +7700 +6600 +ENDCHAR +STARTCHAR uni1E86 +ENCODING 7814 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 11 2 0 +BITMAP +0C00 +0000 +CCC0 +CCC0 +CD80 +DD80 +DD00 +ED00 +EE00 +4400 +4400 +ENDCHAR +STARTCHAR uni1E87 +ENCODING 7815 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 9 1 0 +BITMAP +0C00 +0000 +CCC0 +CCC0 +DD80 +DD80 +5500 +7700 +6600 +ENDCHAR +STARTCHAR uni1E88 +ENCODING 7816 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 11 2 -2 +BITMAP +CCC0 +CCC0 +CD80 +DD80 +DD00 +ED00 +EE00 +4400 +4400 +0000 +1800 +ENDCHAR +STARTCHAR uni1E89 +ENCODING 7817 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 9 1 -2 +BITMAP +CCC0 +CCC0 +DD80 +DD80 +5500 +7700 +6600 +0000 +0C00 +ENDCHAR +STARTCHAR uni1E8A +ENCODING 7818 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 10 11 1 0 +BITMAP +0C00 +0000 +30C0 +3180 +1B00 +1E00 +0C00 +1E00 +3600 +6300 +C300 +ENDCHAR +STARTCHAR uni1E8B +ENCODING 7819 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +0C +00 +33 +36 +1C +18 +38 +6C +CC +ENDCHAR +STARTCHAR uni1E8C +ENCODING 7820 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 10 11 1 0 +BITMAP +1B00 +0000 +30C0 +3180 +1B00 +1E00 +0C00 +1E00 +3600 +6300 +C300 +ENDCHAR +STARTCHAR uni1E8D +ENCODING 7821 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 9 0 0 +BITMAP +36 +00 +33 +36 +1C +18 +38 +6C +CC +ENDCHAR +STARTCHAR uni1E8E +ENCODING 7822 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 7 11 2 0 +BITMAP +18 +00 +C6 +C6 +6C +6C +38 +30 +30 +60 +60 +ENDCHAR +STARTCHAR uni1E8F +ENCODING 7823 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 12 1 -3 +BITMAP +30 +00 +CC +CC +CC +D8 +50 +70 +60 +60 +C0 +80 +ENDCHAR +STARTCHAR uni1E90 +ENCODING 7824 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 13 0 0 +BITMAP +0400 +0E00 +1B00 +0000 +3F80 +0300 +0600 +0C00 +1800 +3000 +6000 +C000 +FE00 +ENDCHAR +STARTCHAR uni1E91 +ENCODING 7825 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 7 11 0 0 +BITMAP +08 +1C +36 +00 +3E +06 +0C +38 +60 +C0 +F8 +ENDCHAR +STARTCHAR uni1E92 +ENCODING 7826 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 11 0 -2 +BITMAP +3F80 +0300 +0600 +0C00 +1800 +3000 +6000 +C000 +FE00 +0000 +3000 +ENDCHAR +STARTCHAR uni1E93 +ENCODING 7827 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 7 9 0 -2 +BITMAP +3E +06 +0C +38 +60 +C0 +F8 +00 +30 +ENDCHAR +STARTCHAR uni1E94 +ENCODING 7828 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 11 0 -2 +BITMAP +3F80 +0300 +0600 +0C00 +1800 +3000 +6000 +C000 +FE00 +0000 +7800 +ENDCHAR +STARTCHAR uni1E95 +ENCODING 7829 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 7 9 0 -2 +BITMAP +3E +06 +0C +38 +60 +C0 +F8 +00 +78 +ENDCHAR +STARTCHAR uni1E96 +ENCODING 7830 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 11 0 -2 +BITMAP +18 +18 +36 +3B +63 +66 +66 +CC +CC +00 +3C +ENDCHAR +STARTCHAR uni1E97 +ENCODING 7831 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 6 11 1 0 +BITMAP +6C +00 +18 +18 +7C +30 +60 +60 +60 +C0 +E0 +ENDCHAR +STARTCHAR uni1E98 +ENCODING 7832 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 11 1 0 +BITMAP +0E00 +1B00 +0E00 +0000 +CCC0 +CCC0 +DD80 +DD80 +5500 +7700 +6600 +ENDCHAR +STARTCHAR uni1E99 +ENCODING 7833 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 14 1 -3 +BITMAP +38 +6C +38 +00 +CC +CC +CC +D8 +50 +70 +60 +60 +C0 +80 +ENDCHAR +STARTCHAR uni1EA0 +ENCODING 7840 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 11 0 -2 +BITMAP +06 +0E +0B +1B +33 +3F +63 +C3 +C3 +00 +18 +ENDCHAR +STARTCHAR uni1EA1 +ENCODING 7841 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 9 0 -2 +BITMAP +3C +66 +06 +7C +CC +98 +EC +00 +30 +ENDCHAR +STARTCHAR uni1EA4 +ENCODING 7844 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 15 0 0 +BITMAP +0300 +0600 +0000 +0700 +0D80 +0000 +0600 +0600 +0F00 +1B00 +3300 +3F00 +6300 +C300 +C300 +ENDCHAR +STARTCHAR uni1EA5 +ENCODING 7845 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 13 0 0 +BITMAP +0C +18 +00 +1C +36 +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR uni1EA6 +ENCODING 7846 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 15 0 0 +BITMAP +0C00 +0600 +0000 +0700 +0D80 +0000 +0600 +0600 +0F00 +1B00 +3300 +3F00 +6300 +C300 +C300 +ENDCHAR +STARTCHAR uni1EA7 +ENCODING 7847 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 13 0 0 +BITMAP +30 +18 +00 +1C +36 +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR uni1EAA +ENCODING 7850 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 15 0 0 +BITMAP +0D00 +1600 +0000 +0700 +0D80 +0000 +0600 +0600 +0F00 +1B00 +3300 +3F00 +6300 +C300 +C300 +ENDCHAR +STARTCHAR uni1EAB +ENCODING 7851 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 13 0 0 +BITMAP +1A +2C +00 +1C +36 +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR uni1EAC +ENCODING 7852 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 15 0 -2 +BITMAP +04 +0E +1B +00 +06 +0E +0B +1B +33 +3F +63 +C3 +C3 +00 +18 +ENDCHAR +STARTCHAR uni1EAD +ENCODING 7853 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 13 0 -2 +BITMAP +08 +1C +36 +00 +3C +66 +06 +7C +CC +98 +EC +00 +30 +ENDCHAR +STARTCHAR uni1EAE +ENCODING 7854 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 15 0 0 +BITMAP +06 +0C +00 +1B +0E +00 +06 +0E +0B +1B +33 +3F +63 +C3 +C3 +ENDCHAR +STARTCHAR uni1EAF +ENCODING 7855 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 13 0 0 +BITMAP +18 +30 +00 +6C +38 +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR uni1EB0 +ENCODING 7856 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 15 0 0 +BITMAP +18 +0C +00 +1B +0E +00 +06 +0E +0B +1B +33 +3F +63 +C3 +C3 +ENDCHAR +STARTCHAR uni1EB1 +ENCODING 7857 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 13 0 0 +BITMAP +30 +18 +00 +6C +38 +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR uni1EB4 +ENCODING 7860 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 15 0 0 +BITMAP +0D +16 +00 +1B +0E +00 +06 +0E +0B +1B +33 +3F +63 +C3 +C3 +ENDCHAR +STARTCHAR uni1EB5 +ENCODING 7861 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 13 0 0 +BITMAP +34 +58 +00 +6C +38 +00 +3C +66 +06 +7C +CC +98 +EC +ENDCHAR +STARTCHAR uni1EB6 +ENCODING 7862 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 14 0 -2 +BITMAP +1B +0E +00 +06 +0E +0B +1B +33 +3F +63 +C3 +C3 +00 +18 +ENDCHAR +STARTCHAR uni1EB7 +ENCODING 7863 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 7 12 0 -2 +BITMAP +36 +1C +00 +3C +66 +06 +7C +CC +98 +EC +00 +30 +ENDCHAR +STARTCHAR uni1EB8 +ENCODING 7864 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 11 1 -2 +BITMAP +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +0000 +3000 +ENDCHAR +STARTCHAR uni1EB9 +ENCODING 7865 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 9 0 -2 +BITMAP +1E +33 +63 +7E +C0 +CC +78 +00 +30 +ENDCHAR +STARTCHAR uni1EBC +ENCODING 7868 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 12 1 0 +BITMAP +0D00 +1600 +0000 +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR uni1EBD +ENCODING 7869 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 10 0 0 +BITMAP +1A +2C +00 +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR uni1EBE +ENCODING 7870 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 15 1 0 +BITMAP +0300 +0600 +0000 +0700 +0D80 +0000 +1F80 +1000 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR uni1EBF +ENCODING 7871 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 13 0 0 +BITMAP +06 +0C +00 +0E +1B +00 +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR uni1EC0 +ENCODING 7872 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 15 1 0 +BITMAP +0C00 +0600 +0000 +0700 +0D80 +0000 +1F80 +1000 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR uni1EC1 +ENCODING 7873 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 13 0 0 +BITMAP +18 +0C +00 +0E +1B +00 +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR uni1EC4 +ENCODING 7876 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 15 1 0 +BITMAP +0D00 +1600 +0000 +0700 +0D80 +0000 +1F80 +1000 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +ENDCHAR +STARTCHAR uni1EC5 +ENCODING 7877 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 13 0 0 +BITMAP +0D +16 +00 +0E +1B +00 +1E +33 +63 +7E +C0 +CC +78 +ENDCHAR +STARTCHAR uni1EC6 +ENCODING 7878 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 9 15 1 -2 +BITMAP +0800 +1C00 +3600 +0000 +1F80 +1800 +3000 +3000 +7E00 +6000 +6000 +C000 +FC00 +0000 +3000 +ENDCHAR +STARTCHAR uni1EC7 +ENCODING 7879 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 13 0 -2 +BITMAP +08 +1C +36 +00 +1E +33 +63 +7E +C0 +CC +78 +00 +30 +ENDCHAR +STARTCHAR uni1ECA +ENCODING 7882 +SWIDTH 278 0 +DWIDTH 5 0 +BBX 5 11 1 -2 +BITMAP +18 +18 +30 +30 +60 +60 +60 +C0 +C0 +00 +60 +ENDCHAR +STARTCHAR uni1ECB +ENCODING 7883 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 5 11 0 -2 +BITMAP +18 +00 +30 +30 +60 +60 +60 +C0 +C0 +00 +60 +ENDCHAR +STARTCHAR uni1ECC +ENCODING 7884 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 11 1 -2 +BITMAP +0F00 +3980 +3180 +6180 +6300 +C300 +C600 +CE00 +7800 +0000 +1800 +ENDCHAR +STARTCHAR uni1ECD +ENCODING 7885 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 -2 +BITMAP +1E +33 +63 +66 +C6 +CC +78 +00 +30 +ENDCHAR +STARTCHAR uni1ED0 +ENCODING 7888 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 15 1 0 +BITMAP +0300 +0600 +0000 +0700 +0D80 +0000 +0F00 +3980 +3180 +6180 +C300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR uni1ED1 +ENCODING 7889 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 13 0 0 +BITMAP +06 +0C +00 +0E +1B +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR uni1ED2 +ENCODING 7890 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 15 1 0 +BITMAP +0C00 +0600 +0000 +0700 +0D80 +0000 +0F00 +3980 +3180 +6180 +C300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR uni1ED3 +ENCODING 7891 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 13 0 0 +BITMAP +18 +0C +00 +0E +1B +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR uni1ED6 +ENCODING 7894 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 15 1 0 +BITMAP +0D00 +1600 +0000 +0700 +0D80 +0000 +0F00 +3980 +3180 +6180 +C300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR uni1ED7 +ENCODING 7895 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 13 0 0 +BITMAP +0D +16 +00 +0E +1B +00 +1E +33 +63 +66 +C6 +CC +78 +ENDCHAR +STARTCHAR uni1ED8 +ENCODING 7896 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 9 15 1 -2 +BITMAP +0400 +0E00 +1B00 +0000 +0F00 +3980 +3180 +6180 +6300 +C300 +C600 +CE00 +7800 +0000 +1800 +ENDCHAR +STARTCHAR uni1ED9 +ENCODING 7897 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 13 0 -2 +BITMAP +08 +1C +36 +00 +1E +33 +63 +66 +C6 +CC +78 +00 +30 +ENDCHAR +STARTCHAR uni1EDA +ENCODING 7898 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 11 12 1 0 +BITMAP +0300 +0600 +0000 +0F60 +39E0 +31C0 +6180 +6300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR uni1EDB +ENCODING 7899 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 11 10 0 0 +BITMAP +0300 +0600 +0000 +1E60 +3360 +63C0 +6600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR uni1EDC +ENCODING 7900 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 11 12 1 0 +BITMAP +0600 +0300 +0000 +0F60 +39E0 +31C0 +6180 +6300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR uni1EDD +ENCODING 7901 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 11 10 0 0 +BITMAP +0C00 +0600 +0000 +1E60 +3360 +63C0 +6600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR uni1EE0 +ENCODING 7904 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 11 12 1 0 +BITMAP +0680 +0B00 +0000 +0F60 +39E0 +31C0 +6180 +6300 +C300 +C600 +CE00 +7800 +ENDCHAR +STARTCHAR uni1EE1 +ENCODING 7905 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 11 10 0 0 +BITMAP +0680 +0B00 +0000 +1E60 +3360 +63C0 +6600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR uni1EE2 +ENCODING 7906 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 11 11 1 -2 +BITMAP +0F60 +39E0 +31C0 +6180 +6300 +C300 +C600 +CE00 +7800 +0000 +1800 +ENDCHAR +STARTCHAR uni1EE3 +ENCODING 7907 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 11 9 0 -2 +BITMAP +1E60 +3360 +63C0 +6600 +C600 +CC00 +7800 +0000 +1800 +ENDCHAR +STARTCHAR uni1EE4 +ENCODING 7908 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 11 1 -2 +BITMAP +3180 +3180 +6300 +6300 +6300 +C600 +C600 +CC00 +7800 +0000 +1800 +ENDCHAR +STARTCHAR uni1EE5 +ENCODING 7909 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 8 9 0 -2 +BITMAP +33 +33 +63 +66 +C6 +CC +74 +00 +30 +ENDCHAR +STARTCHAR uni1EE8 +ENCODING 7912 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 11 12 1 0 +BITMAP +0300 +0600 +0000 +31E0 +31E0 +63C0 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR uni1EE9 +ENCODING 7913 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 11 10 0 0 +BITMAP +0300 +0600 +0000 +3360 +3360 +63C0 +6600 +C600 +CC00 +7400 +ENDCHAR +STARTCHAR uni1EEA +ENCODING 7914 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 11 12 1 0 +BITMAP +0C00 +0600 +0000 +31E0 +31E0 +63C0 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR uni1EEB +ENCODING 7915 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 11 10 0 0 +BITMAP +0C00 +0600 +0000 +3360 +3360 +63C0 +6600 +C600 +CC00 +7400 +ENDCHAR +STARTCHAR uni1EEE +ENCODING 7918 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 11 12 1 0 +BITMAP +0680 +0B00 +0000 +31E0 +31E0 +63C0 +6300 +6300 +C600 +C600 +CC00 +7800 +ENDCHAR +STARTCHAR uni1EEF +ENCODING 7919 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 11 10 0 0 +BITMAP +0680 +0B00 +0000 +3360 +3360 +63C0 +6600 +C600 +CC00 +7400 +ENDCHAR +STARTCHAR uni1EF0 +ENCODING 7920 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 11 11 1 -2 +BITMAP +31E0 +31E0 +63C0 +6300 +6300 +C600 +C600 +CC00 +7800 +0000 +1800 +ENDCHAR +STARTCHAR uni1EF1 +ENCODING 7921 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 11 9 0 -2 +BITMAP +3360 +3360 +63C0 +6600 +C600 +CC00 +7400 +0000 +1800 +ENDCHAR +STARTCHAR Ygrave +ENCODING 7922 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 7 12 2 0 +BITMAP +30 +18 +00 +C6 +C6 +6C +6C +38 +30 +30 +60 +60 +ENDCHAR +STARTCHAR ygrave +ENCODING 7923 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 13 1 -3 +BITMAP +60 +30 +00 +CC +CC +CC +D8 +50 +70 +60 +60 +C0 +80 +ENDCHAR +STARTCHAR uni1EF4 +ENCODING 7924 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 7 11 2 -2 +BITMAP +C6 +C6 +6C +6C +38 +30 +30 +60 +60 +00 +30 +ENDCHAR +STARTCHAR uni1EF5 +ENCODING 7925 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 12 1 -5 +BITMAP +CC +CC +CC +D8 +50 +70 +60 +60 +C0 +80 +00 +60 +ENDCHAR +STARTCHAR uni1EF8 +ENCODING 7928 +SWIDTH 667 0 +DWIDTH 7 0 +BBX 7 12 2 0 +BITMAP +34 +58 +00 +C6 +C6 +6C +6C +38 +30 +30 +60 +60 +ENDCHAR +STARTCHAR uni1EF9 +ENCODING 7929 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 13 1 -3 +BITMAP +34 +58 +00 +CC +CC +CC +D8 +50 +70 +60 +60 +C0 +80 +ENDCHAR +STARTCHAR uni2000 +ENCODING 8192 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2001 +ENCODING 8193 +SWIDTH 1000 0 +DWIDTH 13 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2002 +ENCODING 8194 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2003 +ENCODING 8195 +SWIDTH 1000 0 +DWIDTH 13 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2004 +ENCODING 8196 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2005 +ENCODING 8197 +SWIDTH 250 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2006 +ENCODING 8198 +SWIDTH 167 0 +DWIDTH 2 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2007 +ENCODING 8199 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2008 +ENCODING 8200 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2009 +ENCODING 8201 +SWIDTH 200 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni200A +ENCODING 8202 +SWIDTH 100 0 +DWIDTH 1 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni200B +ENCODING 8203 +SWIDTH 0 0 +DWIDTH 0 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2010 +ENCODING 8208 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 1 3 +BITMAP +F0 +ENDCHAR +STARTCHAR uni2011 +ENCODING 8209 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 1 3 +BITMAP +F0 +ENDCHAR +STARTCHAR figuredash +ENCODING 8210 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 1 1 3 +BITMAP +FE +ENDCHAR +STARTCHAR endash +ENCODING 8211 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 1 1 3 +BITMAP +FE +ENDCHAR +STARTCHAR emdash +ENCODING 8212 +SWIDTH 1000 0 +DWIDTH 12 0 +BBX 12 1 1 3 +BITMAP +FFF0 +ENDCHAR +STARTCHAR afii00208 +ENCODING 8213 +SWIDTH 1000 0 +DWIDTH 12 0 +BBX 12 1 1 3 +BITMAP +FFF0 +ENDCHAR +STARTCHAR quoteleft +ENCODING 8216 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 3 3 3 6 +BITMAP +60 +C0 +C0 +ENDCHAR +STARTCHAR quoteright +ENCODING 8217 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 3 3 3 6 +BITMAP +60 +60 +C0 +ENDCHAR +STARTCHAR quotesinglbase +ENCODING 8218 +SWIDTH 278 0 +DWIDTH 2 0 +BBX 3 3 -1 -1 +BITMAP +60 +60 +C0 +ENDCHAR +STARTCHAR quotereversed +ENCODING 8219 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 3 3 3 6 +BITMAP +C0 +C0 +60 +ENDCHAR +STARTCHAR quotedblleft +ENCODING 8220 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 6 3 2 6 +BITMAP +6C +D8 +D8 +ENDCHAR +STARTCHAR quotedblright +ENCODING 8221 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 6 3 2 6 +BITMAP +6C +6C +D8 +ENDCHAR +STARTCHAR quotedblbase +ENCODING 8222 +SWIDTH 500 0 +DWIDTH 5 0 +BBX 6 3 -1 -1 +BITMAP +6C +6C +D8 +ENDCHAR +STARTCHAR uni201F +ENCODING 8223 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 6 3 2 6 +BITMAP +D8 +D8 +6C +ENDCHAR +STARTCHAR dagger +ENCODING 8224 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 12 1 -3 +BITMAP +0C +0C +18 +7E +18 +30 +30 +60 +60 +60 +C0 +C0 +ENDCHAR +STARTCHAR daggerdbl +ENCODING 8225 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 8 12 0 -3 +BITMAP +06 +06 +0C +3F +0C +18 +18 +30 +FC +30 +60 +60 +ENDCHAR +STARTCHAR bullet +ENCODING 8226 +SWIDTH 350 0 +DWIDTH 6 0 +BBX 4 3 1 2 +BITMAP +70 +F0 +E0 +ENDCHAR +STARTCHAR ellipsis +ENCODING 8230 +SWIDTH 1000 0 +DWIDTH 12 0 +BBX 10 1 1 0 +BITMAP +CCC0 +ENDCHAR +STARTCHAR perthousand +ENCODING 8240 +SWIDTH 1000 0 +DWIDTH 14 0 +BBX 13 8 1 0 +BITMAP +3180 +6B00 +3600 +0C00 +1800 +3630 +6D68 +C630 +ENDCHAR +STARTCHAR guilsinglleft +ENCODING 8249 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 5 5 1 1 +BITMAP +18 +70 +C0 +60 +30 +ENDCHAR +STARTCHAR guilsinglright +ENCODING 8250 +SWIDTH 333 0 +DWIDTH 6 0 +BBX 5 5 1 1 +BITMAP +60 +30 +18 +70 +C0 +ENDCHAR +STARTCHAR fraction +ENCODING 8260 +SWIDTH 167 0 +DWIDTH 5 0 +BBX 8 8 -1 0 +BITMAP +03 +06 +0C +18 +10 +30 +60 +C0 +ENDCHAR +STARTCHAR oneinferior +ENCODING 8321 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 5 1 -3 +BITMAP +20 +E0 +20 +40 +40 +ENDCHAR +STARTCHAR twoinferior +ENCODING 8322 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 5 1 -3 +BITMAP +60 +B0 +20 +40 +F0 +ENDCHAR +STARTCHAR threeinferior +ENCODING 8323 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 5 1 -3 +BITMAP +70 +30 +60 +30 +E0 +ENDCHAR +STARTCHAR uni20A5 +ENCODING 8357 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 12 9 0 -1 +BITMAP +0040 +2EE0 +33B0 +3330 +6660 +6660 +CCC0 +DCC0 +1000 +ENDCHAR +STARTCHAR uni20A6 +ENCODING 8358 +SWIDTH 722 0 +DWIDTH 10 0 +BBX 10 9 1 0 +BITMAP +18C0 +18C0 +3980 +3F80 +6980 +7F00 +6700 +C600 +C600 +ENDCHAR +STARTCHAR uni20A9 +ENCODING 8361 +SWIDTH 944 0 +DWIDTH 10 0 +BBX 10 9 2 0 +BITMAP +CCC0 +CCC0 +CD80 +DF80 +DD00 +FF00 +EE00 +4400 +4400 +ENDCHAR +STARTCHAR Euro +ENCODING 8364 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 9 0 0 +BITMAP +0F00 +1980 +3180 +7C00 +6000 +F800 +6300 +6600 +3C00 +ENDCHAR +STARTCHAR uni20AD +ENCODING 8365 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 10 9 1 0 +BITMAP +18C0 +1980 +3300 +3600 +FFC0 +6600 +6600 +C300 +C300 +ENDCHAR +STARTCHAR uni2103 +ENCODING 8451 +SWIDTH 1102 0 +DWIDTH 13 0 +BBX 12 9 2 0 +BITMAP +01E0 +6330 +9630 +9600 +6C00 +0C00 +0C60 +0CC0 +0780 +ENDCHAR +STARTCHAR uni2109 +ENCODING 8457 +SWIDTH 991 0 +DWIDTH 12 0 +BBX 13 9 2 0 +BITMAP +01F8 +6180 +9300 +9300 +67E0 +0600 +0600 +0C00 +0C00 +ENDCHAR +STARTCHAR trademark +ENCODING 8482 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 9 5 3 3 +BITMAP +E880 +4D80 +4A80 +9500 +9500 +ENDCHAR +STARTCHAR uni212A +ENCODING 8490 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 10 9 1 0 +BITMAP +18C0 +1980 +3300 +3600 +3C00 +6600 +6600 +C300 +C300 +ENDCHAR +STARTCHAR uni212B +ENCODING 8491 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 9 12 0 0 +BITMAP +0300 +0480 +0300 +0300 +0700 +0F00 +1B00 +3300 +3F00 +6300 +C300 +C300 +ENDCHAR +STARTCHAR uni2132 +ENCODING 8498 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 9 9 1 0 +BITMAP +0180 +0180 +0300 +0300 +3F00 +0600 +0600 +0C00 +FC00 +ENDCHAR +STARTCHAR minus +ENCODING 8722 +SWIDTH 584 0 +DWIDTH 8 0 +BBX 6 1 2 3 +BITMAP +FC +ENDCHAR +STARTCHAR fraction +ENCODING 8725 +SWIDTH 167 0 +DWIDTH 5 0 +BBX 8 8 -1 0 +BITMAP +03 +06 +0C +18 +10 +30 +60 +C0 +ENDCHAR +STARTCHAR periodcentered +ENCODING 8729 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 2 2 3 +BITMAP +C0 +C0 +ENDCHAR +STARTCHAR uni2236 +ENCODING 8758 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 7 1 0 +BITMAP +30 +30 +00 +00 +00 +C0 +C0 +ENDCHAR +STARTCHAR uni2259 +ENCODING 8793 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 7 1 2 +BITMAP +10 +38 +6C +00 +7C +00 +F8 +ENDCHAR +STARTCHAR uni225A +ENCODING 8794 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 7 1 2 +BITMAP +6C +38 +10 +00 +7C +00 +F8 +ENDCHAR +STARTCHAR notequal +ENCODING 8800 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 7 9 1 -1 +BITMAP +02 +06 +0C +7C +10 +F8 +60 +C0 +80 +ENDCHAR +STARTCHAR equivalence +ENCODING 8801 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 5 0 1 +BITMAP +FC +00 +FC +00 +FC +ENDCHAR +STARTCHAR uni2262 +ENCODING 8802 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 7 9 0 -1 +BITMAP +02 +06 +FC +18 +FC +30 +FC +C0 +80 +ENDCHAR +STARTCHAR lessequal +ENCODING 8804 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 7 2 -1 +BITMAP +1C +70 +C0 +60 +30 +00 +FC +ENDCHAR +STARTCHAR greaterequal +ENCODING 8805 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 7 1 -1 +BITMAP +30 +18 +0C +38 +E0 +00 +FC +ENDCHAR +STARTCHAR uni226E +ENCODING 8814 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 7 9 2 -1 +BITMAP +02 +06 +1C +78 +D0 +70 +70 +C0 +80 +ENDCHAR +STARTCHAR uni226F +ENCODING 8815 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 7 9 1 -1 +BITMAP +02 +06 +3C +18 +1C +38 +E0 +C0 +80 +ENDCHAR +STARTCHAR uni2270 +ENCODING 8816 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 7 9 2 -2 +BITMAP +02 +1E +7C +D8 +70 +30 +60 +FC +80 +ENDCHAR +STARTCHAR uni2271 +ENCODING 8817 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 7 9 1 -2 +BITMAP +02 +36 +1C +1C +38 +F0 +60 +FC +80 +ENDCHAR +STARTCHAR fi +ENCODING -1 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 10 9 0 0 +BITMAP +0EC0 +1800 +7D80 +3300 +3300 +6600 +6600 +CC00 +CC00 +ENDCHAR +STARTCHAR fl +ENCODING -1 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 10 9 0 0 +BITMAP +0EC0 +1980 +7D80 +3300 +3300 +6600 +6600 +CC00 +CC00 +ENDCHAR +ENDFONT diff --git a/gui/themes/fonts/helvR12-iso-8859-1.bdf b/gui/themes/fonts/helvR12-iso-8859-1.bdf new file mode 100644 index 0000000000..1f27c247db --- /dev/null +++ b/gui/themes/fonts/helvR12-iso-8859-1.bdf @@ -0,0 +1,3048 @@ +STARTFONT 2.1 +COMMENT AUTOMATICALLY GENERATED FILE. DO NOT EDIT! +COMMENT Generated with 'ucs2any.pl helvR12.bdf ../../../fonts/util/map-ISO8859-1 ISO8859-1' +COMMENT from an ISO10646-1 encoded source BDF font. +COMMENT ucs2any.pl by Markus Kuhn <mkuhn@acm.org>, 2000. +FONT -Adobe-Helvetica-Medium-R-Normal--12-120-75-75-P-67-ISO8859-1 +SIZE 12 75 75 +FONTBOUNDINGBOX 11 15 0 -3 +COMMENT $Xorg: $ +COMMENT ISO10646-1 extension by Markus Kuhn <mkuhn@acm.org>, 2001-03-20 +COMMENT +COMMENT + +COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated. +COMMENT Copyright 1988, 1994 Digital Equipment Corporation. +COMMENT +COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be +COMMENT registered in certain jurisdictions. +COMMENT Permission to use these trademarks is hereby granted only in +COMMENT association with the images described in this file. +COMMENT +COMMENT Permission to use, copy, modify, distribute and sell this software +COMMENT and its documentation for any purpose and without fee is hereby +COMMENT granted, provided that the above copyright notices appear in all +COMMENT copies and that both those copyright notices and this permission +COMMENT notice appear in supporting documentation, and that the names of +COMMENT Adobe Systems and Digital Equipment Corporation not be used in +COMMENT advertising or publicity pertaining to distribution of the software +COMMENT without specific, written prior permission. Adobe Systems and +COMMENT Digital Equipment Corporation make no representations about the +COMMENT suitability of this software for any purpose. It is provided "as +COMMENT is" without express or implied warranty. +COMMENT - +STARTPROPERTIES 26 +FOUNDRY "Adobe" +FAMILY_NAME "Helvetica" +WEIGHT_NAME "Medium" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 12 +POINT_SIZE 120 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "P" +AVERAGE_WIDTH 67 +CHARSET_REGISTRY "ISO8859" +CHARSET_ENCODING "1" +CAP_HEIGHT 9 +X_HEIGHT 7 +FONT_ASCENT 11 +FONT_DESCENT 3 +FACE_NAME "Helvetica" +COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved." +NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. " +_DEC_DEVICE_FONTNAMES "PS=Helvetica" +DEFAULT_CHAR 0 +RELATIVE_SETWIDTH 50 +RELATIVE_WEIGHT 50 +FULL_NAME "Helvetica" +ENDPROPERTIES +CHARS 192 +STARTCHAR defaultchar +ENCODING 0 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +AA +00 +82 +00 +82 +00 +82 +00 +AA +ENDCHAR +STARTCHAR space +ENCODING 32 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 9 1 0 +BITMAP +80 +80 +80 +80 +80 +80 +80 +00 +80 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 355 0 +DWIDTH 5 0 +BBX 3 3 1 6 +BITMAP +A0 +A0 +A0 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +28 +28 +FC +28 +FC +50 +50 +50 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -1 +BITMAP +20 +70 +A8 +A0 +70 +28 +A8 +A8 +70 +20 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +6200 +9400 +9400 +6800 +0800 +1300 +1480 +1480 +2300 +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +30 +48 +48 +30 +50 +8A +84 +8C +72 +ENDCHAR +STARTCHAR quotesingle +ENCODING 39 +SWIDTH 191 0 +DWIDTH 3 0 +BBX 1 3 1 6 +BITMAP +80 +80 +80 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 12 1 -3 +BITMAP +20 +40 +40 +80 +80 +80 +80 +80 +80 +40 +40 +20 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 12 0 -3 +BITMAP +80 +40 +40 +20 +20 +20 +20 +20 +20 +40 +40 +80 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 3 3 1 6 +BITMAP +A0 +40 +A0 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +20 +20 +F8 +20 +20 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 3 1 -2 +BITMAP +40 +40 +80 +ENDCHAR +STARTCHAR hyphen +ENCODING 45 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 0 3 +BITMAP +F0 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 1 1 0 +BITMAP +80 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 9 0 0 +BITMAP +10 +10 +20 +20 +40 +40 +40 +80 +80 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +88 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 3 9 1 0 +BITMAP +20 +E0 +20 +20 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +08 +10 +20 +40 +80 +80 +F8 +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +08 +30 +08 +08 +88 +88 +70 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +08 +18 +28 +28 +48 +88 +FC +08 +08 +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +F8 +80 +80 +F0 +08 +08 +88 +88 +70 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +80 +B0 +C8 +88 +88 +88 +70 +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +F8 +08 +10 +10 +20 +20 +20 +40 +40 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +88 +70 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +88 +88 +78 +08 +08 +88 +70 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 6 1 0 +BITMAP +80 +00 +00 +00 +00 +80 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 8 0 -2 +BITMAP +40 +00 +00 +00 +00 +40 +40 +80 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 5 0 1 +BITMAP +0C +30 +C0 +30 +0C +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 3 1 2 +BITMAP +F8 +00 +F8 +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 5 1 1 +BITMAP +C0 +30 +0C +30 +C0 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +88 +10 +10 +20 +20 +00 +20 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 1015 0 +DWIDTH 12 0 +BBX 10 10 1 -1 +BITMAP +1F00 +6080 +4D40 +9240 +A240 +A240 +A680 +9B00 +4000 +3E00 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +10 +28 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +F8 +84 +84 +84 +F8 +84 +84 +84 +F8 +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +3C +42 +80 +80 +80 +80 +80 +42 +3C +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +F8 +84 +82 +82 +82 +82 +82 +84 +F8 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +FC +80 +80 +80 +F8 +80 +80 +80 +80 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +3C +42 +80 +80 +8E +82 +82 +46 +3A +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +82 +82 +82 +82 +FE +82 +82 +82 +82 +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 9 1 0 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +08 +08 +08 +08 +08 +08 +88 +88 +70 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 9 1 0 +BITMAP +84 +88 +90 +A0 +E0 +90 +88 +84 +82 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +F8 +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 833 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +8080 +C180 +C180 +A280 +A280 +9480 +9480 +8880 +8880 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +82 +C2 +A2 +A2 +92 +8A +8A +86 +82 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +F8 +84 +84 +84 +F8 +80 +80 +80 +80 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +3C +42 +81 +81 +81 +89 +85 +42 +3D +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +F8 +84 +84 +84 +F8 +88 +84 +84 +84 +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +78 +84 +80 +60 +18 +04 +84 +84 +78 +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +FE +10 +10 +10 +10 +10 +10 +10 +10 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +82 +82 +44 +44 +44 +28 +28 +10 +10 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 944 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +8880 +8880 +8880 +4900 +5500 +5500 +2200 +2200 +2200 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +82 +44 +44 +28 +10 +28 +44 +44 +82 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +82 +82 +44 +44 +28 +10 +10 +10 +10 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 611 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +FE +02 +04 +08 +10 +20 +40 +80 +FE +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 12 1 -3 +BITMAP +C0 +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +C0 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 9 0 0 +BITMAP +80 +80 +40 +40 +20 +20 +20 +10 +10 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 12 0 -3 +BITMAP +C0 +40 +40 +40 +40 +40 +40 +40 +40 +40 +40 +C0 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 469 0 +DWIDTH 6 0 +BBX 5 3 0 5 +BITMAP +20 +50 +88 +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 1 0 -2 +BITMAP +FE +ENDCHAR +STARTCHAR grave +ENCODING 96 +SWIDTH 333 0 +DWIDTH 2 0 +BBX 2 2 0 8 +BITMAP +80 +40 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 1 0 +BITMAP +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +80 +80 +B0 +C8 +88 +88 +88 +C8 +B0 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +70 +88 +80 +80 +80 +88 +70 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +08 +08 +68 +98 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 9 0 0 +BITMAP +30 +40 +E0 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +68 +98 +88 +88 +88 +98 +68 +08 +88 +70 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +80 +80 +B0 +C8 +88 +88 +88 +88 +88 +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 1 9 1 0 +BITMAP +80 +00 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 2 12 0 -3 +BITMAP +40 +00 +40 +40 +40 +40 +40 +40 +40 +40 +40 +80 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 9 1 0 +BITMAP +80 +80 +90 +A0 +C0 +C0 +A0 +90 +88 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 1 9 1 0 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 833 0 +DWIDTH 9 0 +BBX 7 7 1 0 +BITMAP +A4 +DA +92 +92 +92 +92 +92 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +B0 +C8 +88 +88 +88 +88 +88 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +B0 +C8 +88 +88 +88 +C8 +B0 +80 +80 +80 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +68 +98 +88 +88 +88 +98 +68 +08 +08 +08 +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 7 1 0 +BITMAP +A0 +C0 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 7 1 0 +BITMAP +60 +90 +80 +60 +10 +90 +60 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 0 0 +BITMAP +40 +40 +E0 +40 +40 +40 +40 +40 +60 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +88 +88 +88 +50 +50 +20 +20 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 7 0 0 +BITMAP +8880 +8880 +4900 +4900 +5500 +2200 +2200 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 6 7 0 0 +BITMAP +84 +48 +30 +30 +48 +84 +84 +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +88 +88 +88 +90 +50 +50 +20 +20 +40 +80 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 7 1 0 +BITMAP +F0 +10 +20 +40 +40 +80 +F0 +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 334 0 +DWIDTH 4 0 +BBX 4 12 0 -3 +BITMAP +30 +40 +40 +40 +40 +80 +40 +40 +40 +40 +40 +30 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 260 0 +DWIDTH 3 0 +BBX 1 12 1 -3 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 334 0 +DWIDTH 4 0 +BBX 4 12 0 -3 +BITMAP +C0 +20 +20 +20 +20 +10 +20 +20 +20 +20 +20 +C0 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 2 0 3 +BITMAP +64 +98 +ENDCHAR +STARTCHAR space +ENCODING 160 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclamdown +ENCODING 161 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 1 10 1 -3 +BITMAP +80 +00 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR cent +ENCODING 162 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 -1 +BITMAP +10 +70 +A8 +A0 +A0 +A0 +C8 +70 +40 +ENDCHAR +STARTCHAR sterling +ENCODING 163 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +30 +48 +40 +40 +F0 +20 +20 +48 +B0 +ENDCHAR +STARTCHAR currency +ENCODING 164 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 6 0 1 +BITMAP +84 +78 +48 +48 +78 +84 +ENDCHAR +STARTCHAR yen +ENCODING 165 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +88 +88 +50 +20 +F8 +20 +F8 +20 +20 +ENDCHAR +STARTCHAR brokenbar +ENCODING 166 +SWIDTH 260 0 +DWIDTH 3 0 +BBX 1 11 1 -2 +BITMAP +80 +80 +80 +80 +00 +00 +00 +80 +80 +80 +80 +ENDCHAR +STARTCHAR section +ENCODING 167 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 12 0 -3 +BITMAP +70 +88 +80 +60 +90 +88 +88 +48 +30 +08 +88 +70 +ENDCHAR +STARTCHAR dieresis +ENCODING 168 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 1 0 8 +BITMAP +A0 +ENDCHAR +STARTCHAR copyright +ENCODING 169 +SWIDTH 737 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +3E00 +4100 +9C80 +A280 +A080 +A280 +9C80 +4100 +3E00 +ENDCHAR +STARTCHAR ordfeminine +ENCODING 170 +SWIDTH 370 0 +DWIDTH 5 0 +BBX 3 5 1 4 +BITMAP +E0 +20 +A0 +00 +E0 +ENDCHAR +STARTCHAR guillemotleft +ENCODING 171 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +28 +50 +A0 +50 +28 +ENDCHAR +STARTCHAR logicalnot +ENCODING 172 +SWIDTH 584 0 +DWIDTH 8 0 +BBX 6 4 1 2 +BITMAP +FC +04 +04 +04 +ENDCHAR +STARTCHAR hyphen +ENCODING 173 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 0 3 +BITMAP +F0 +ENDCHAR +STARTCHAR registered +ENCODING 174 +SWIDTH 737 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +3E00 +4100 +9C80 +9480 +9880 +9480 +9480 +4100 +3E00 +ENDCHAR +STARTCHAR macron +ENCODING 175 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 1 0 8 +BITMAP +F0 +ENDCHAR +STARTCHAR degree +ENCODING 176 +SWIDTH 400 0 +DWIDTH 5 0 +BBX 4 4 0 4 +BITMAP +60 +90 +90 +60 +ENDCHAR +STARTCHAR plusminus +ENCODING 177 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +20 +20 +F8 +20 +20 +00 +F8 +ENDCHAR +STARTCHAR twosuperior +ENCODING 178 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 5 0 3 +BITMAP +60 +90 +20 +40 +F0 +ENDCHAR +STARTCHAR threesuperior +ENCODING 179 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 5 0 3 +BITMAP +E0 +20 +40 +20 +C0 +ENDCHAR +STARTCHAR acute +ENCODING 180 +SWIDTH 333 0 +DWIDTH 2 0 +BBX 2 2 0 8 +BITMAP +40 +80 +ENDCHAR +STARTCHAR mu +ENCODING 181 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +88 +88 +88 +88 +88 +98 +E8 +80 +80 +80 +ENDCHAR +STARTCHAR paragraph +ENCODING 182 +SWIDTH 537 0 +DWIDTH 7 0 +BBX 6 12 0 -3 +BITMAP +3C +68 +E8 +E8 +E8 +68 +28 +28 +28 +28 +28 +28 +ENDCHAR +STARTCHAR periodcentered +ENCODING 183 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 1 1 3 +BITMAP +80 +ENDCHAR +STARTCHAR cedilla +ENCODING 184 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 4 0 -3 +BITMAP +40 +20 +20 +C0 +ENDCHAR +STARTCHAR onesuperior +ENCODING 185 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 5 1 3 +BITMAP +40 +C0 +40 +40 +40 +ENDCHAR +STARTCHAR ordmasculine +ENCODING 186 +SWIDTH 365 0 +DWIDTH 5 0 +BBX 3 5 1 4 +BITMAP +E0 +A0 +E0 +00 +E0 +ENDCHAR +STARTCHAR guillemotright +ENCODING 187 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +A0 +50 +28 +50 +A0 +ENDCHAR +STARTCHAR onequarter +ENCODING 188 +SWIDTH 834 0 +DWIDTH 10 0 +BBX 9 9 0 0 +BITMAP +4100 +C200 +4400 +4400 +4900 +1300 +1500 +2780 +4100 +ENDCHAR +STARTCHAR onehalf +ENCODING 189 +SWIDTH 834 0 +DWIDTH 10 0 +BBX 9 9 0 0 +BITMAP +4100 +C200 +4400 +4800 +4B00 +1480 +1100 +2200 +4780 +ENDCHAR +STARTCHAR threequarters +ENCODING 190 +SWIDTH 834 0 +DWIDTH 10 0 +BBX 9 9 0 0 +BITMAP +E100 +2200 +4400 +2400 +C900 +0B00 +1500 +1780 +2100 +ENDCHAR +STARTCHAR questiondown +ENCODING 191 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 5 9 1 -3 +BITMAP +20 +00 +20 +20 +40 +40 +88 +88 +70 +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +20 +10 +00 +10 +10 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR Aacute +ENCODING 193 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +08 +10 +00 +10 +10 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR Acircumflex +ENCODING 194 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +10 +28 +00 +10 +10 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR Atilde +ENCODING 195 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +14 +28 +00 +10 +10 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR Adieresis +ENCODING 196 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +28 +00 +10 +10 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR Aring +ENCODING 197 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +10 +28 +10 +10 +10 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR AE +ENCODING 198 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +1F80 +2800 +2800 +4800 +4F80 +7800 +8800 +8800 +8F80 +ENDCHAR +STARTCHAR Ccedilla +ENCODING 199 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +3C +42 +80 +80 +80 +80 +80 +42 +3C +08 +08 +30 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +20 +10 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR Eacute +ENCODING 201 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +08 +10 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR Ecircumflex +ENCODING 202 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +10 +28 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR Edieresis +ENCODING 203 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +28 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR Igrave +ENCODING 204 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 12 0 0 +BITMAP +80 +40 +00 +40 +40 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR Iacute +ENCODING 205 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 12 1 0 +BITMAP +40 +80 +00 +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR Icircumflex +ENCODING 206 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 12 0 0 +BITMAP +40 +A0 +00 +40 +40 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR Idieresis +ENCODING 207 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 11 0 0 +BITMAP +A0 +00 +40 +40 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR Eth +ENCODING 208 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 9 0 0 +BITMAP +7C +42 +41 +41 +F1 +41 +41 +42 +7C +ENDCHAR +STARTCHAR Ntilde +ENCODING 209 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +14 +28 +00 +82 +C2 +A2 +A2 +92 +8A +8A +86 +82 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +10 +08 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR Oacute +ENCODING 211 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +04 +08 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR Ocircumflex +ENCODING 212 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +08 +14 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR Otilde +ENCODING 213 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +14 +28 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR Odieresis +ENCODING 214 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +24 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR multiply +ENCODING 215 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +88 +50 +20 +50 +88 +ENDCHAR +STARTCHAR Oslash +ENCODING 216 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 11 0 -1 +BITMAP +0040 +1E80 +2100 +4280 +4480 +4480 +4880 +5080 +2100 +5E00 +8000 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +20 +10 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR Uacute +ENCODING 218 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +08 +10 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR Ucircumflex +ENCODING 219 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +10 +28 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR Udieresis +ENCODING 220 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +48 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR Yacute +ENCODING 221 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +08 +10 +00 +82 +82 +44 +44 +28 +10 +10 +10 +10 +ENDCHAR +STARTCHAR Thorn +ENCODING 222 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +80 +80 +F8 +84 +84 +84 +F8 +80 +80 +ENDCHAR +STARTCHAR germandbls +ENCODING 223 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +88 +88 +B0 +88 +88 +88 +B0 +ENDCHAR +STARTCHAR agrave +ENCODING 224 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 1 0 +BITMAP +20 +10 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR aacute +ENCODING 225 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 1 0 +BITMAP +10 +20 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR acircumflex +ENCODING 226 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 1 0 +BITMAP +20 +50 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR atilde +ENCODING 227 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 1 0 +BITMAP +28 +50 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR adieresis +ENCODING 228 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +50 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR aring +ENCODING 229 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 1 0 +BITMAP +30 +48 +30 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR ae +ENCODING 230 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 9 7 1 0 +BITMAP +7700 +8880 +0880 +7F80 +8800 +8880 +7700 +ENDCHAR +STARTCHAR ccedilla +ENCODING 231 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +70 +88 +80 +80 +80 +88 +70 +20 +10 +60 +ENDCHAR +STARTCHAR egrave +ENCODING 232 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +40 +20 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR eacute +ENCODING 233 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +10 +20 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR ecircumflex +ENCODING 234 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +20 +50 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR edieresis +ENCODING 235 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +50 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR igrave +ENCODING 236 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 10 0 0 +BITMAP +80 +40 +00 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR iacute +ENCODING 237 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 10 1 0 +BITMAP +40 +80 +00 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR icircumflex +ENCODING 238 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 10 0 0 +BITMAP +40 +A0 +00 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR idieresis +ENCODING 239 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 0 0 +BITMAP +A0 +00 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR eth +ENCODING 240 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +68 +30 +50 +08 +78 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR ntilde +ENCODING 241 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +28 +50 +00 +B0 +C8 +88 +88 +88 +88 +88 +ENDCHAR +STARTCHAR ograve +ENCODING 242 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +40 +20 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR oacute +ENCODING 243 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +10 +20 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR ocircumflex +ENCODING 244 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +20 +50 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR otilde +ENCODING 245 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +28 +50 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR odieresis +ENCODING 246 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +50 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR divide +ENCODING 247 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +20 +00 +F8 +00 +20 +ENDCHAR +STARTCHAR oslash +ENCODING 248 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 7 0 0 +BITMAP +3A +44 +4C +54 +64 +44 +B8 +ENDCHAR +STARTCHAR ugrave +ENCODING 249 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +40 +20 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR uacute +ENCODING 250 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +10 +20 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR ucircumflex +ENCODING 251 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +20 +50 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR udieresis +ENCODING 252 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +50 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR yacute +ENCODING 253 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 13 1 -3 +BITMAP +10 +20 +00 +88 +88 +88 +90 +50 +50 +20 +20 +40 +80 +ENDCHAR +STARTCHAR thorn +ENCODING 254 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 -3 +BITMAP +80 +80 +B0 +C8 +88 +88 +88 +C8 +B0 +80 +80 +80 +ENDCHAR +STARTCHAR ydieresis +ENCODING 255 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 12 1 -3 +BITMAP +50 +00 +88 +88 +48 +50 +50 +30 +20 +20 +20 +C0 +ENDCHAR +ENDFONT diff --git a/gui/themes/fonts/helvR12.bdf b/gui/themes/fonts/helvR12.bdf new file mode 100644 index 0000000000..2e7abc680b --- /dev/null +++ b/gui/themes/fonts/helvR12.bdf @@ -0,0 +1,12688 @@ +STARTFONT 2.1 +FONT -Adobe-Helvetica-Medium-R-Normal--12-120-75-75-P-67-ISO10646-1 +SIZE 12 75 75 +FONTBOUNDINGBOX 14 20 -1 -5 +COMMENT $Xorg: $ +COMMENT ISO10646-1 extension by Markus Kuhn <mkuhn@acm.org>, 2001-03-20 +COMMENT +COMMENT + +COMMENT Copyright 1984-1989, 1994 Adobe Systems Incorporated. +COMMENT Copyright 1988, 1994 Digital Equipment Corporation. +COMMENT +COMMENT Adobe is a trademark of Adobe Systems Incorporated which may be +COMMENT registered in certain jurisdictions. +COMMENT Permission to use these trademarks is hereby granted only in +COMMENT association with the images described in this file. +COMMENT +COMMENT Permission to use, copy, modify, distribute and sell this software +COMMENT and its documentation for any purpose and without fee is hereby +COMMENT granted, provided that the above copyright notices appear in all +COMMENT copies and that both those copyright notices and this permission +COMMENT notice appear in supporting documentation, and that the names of +COMMENT Adobe Systems and Digital Equipment Corporation not be used in +COMMENT advertising or publicity pertaining to distribution of the software +COMMENT without specific, written prior permission. Adobe Systems and +COMMENT Digital Equipment Corporation make no representations about the +COMMENT suitability of this software for any purpose. It is provided "as +COMMENT is" without express or implied warranty. +COMMENT - +STARTPROPERTIES 26 +FOUNDRY "Adobe" +FAMILY_NAME "Helvetica" +WEIGHT_NAME "Medium" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 12 +POINT_SIZE 120 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "P" +AVERAGE_WIDTH 67 +CHARSET_REGISTRY "ISO10646" +CHARSET_ENCODING "1" +CAP_HEIGHT 9 +X_HEIGHT 7 +FONT_ASCENT 11 +FONT_DESCENT 3 +FACE_NAME "Helvetica" +COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved." +NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries. " +_DEC_DEVICE_FONTNAMES "PS=Helvetica" +DEFAULT_CHAR 0 +RELATIVE_SETWIDTH 50 +RELATIVE_WEIGHT 50 +FULL_NAME "Helvetica" +ENDPROPERTIES +CHARS 756 +STARTCHAR char0 +ENCODING 0 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +AA +00 +82 +00 +82 +00 +82 +00 +AA +ENDCHAR +STARTCHAR space +ENCODING 32 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclam +ENCODING 33 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 9 1 0 +BITMAP +80 +80 +80 +80 +80 +80 +80 +00 +80 +ENDCHAR +STARTCHAR quotedbl +ENCODING 34 +SWIDTH 355 0 +DWIDTH 5 0 +BBX 3 3 1 6 +BITMAP +A0 +A0 +A0 +ENDCHAR +STARTCHAR numbersign +ENCODING 35 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 8 0 0 +BITMAP +28 +28 +FC +28 +FC +50 +50 +50 +ENDCHAR +STARTCHAR dollar +ENCODING 36 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -1 +BITMAP +20 +70 +A8 +A0 +70 +28 +A8 +A8 +70 +20 +ENDCHAR +STARTCHAR percent +ENCODING 37 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +6200 +9400 +9400 +6800 +0800 +1300 +1480 +1480 +2300 +ENDCHAR +STARTCHAR ampersand +ENCODING 38 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +30 +48 +48 +30 +50 +8A +84 +8C +72 +ENDCHAR +STARTCHAR quotesingle +ENCODING 39 +SWIDTH 191 0 +DWIDTH 3 0 +BBX 1 3 1 6 +BITMAP +80 +80 +80 +ENDCHAR +STARTCHAR parenleft +ENCODING 40 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 12 1 -3 +BITMAP +20 +40 +40 +80 +80 +80 +80 +80 +80 +40 +40 +20 +ENDCHAR +STARTCHAR parenright +ENCODING 41 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 12 0 -3 +BITMAP +80 +40 +40 +20 +20 +20 +20 +20 +20 +40 +40 +80 +ENDCHAR +STARTCHAR asterisk +ENCODING 42 +SWIDTH 389 0 +DWIDTH 5 0 +BBX 3 3 1 6 +BITMAP +A0 +40 +A0 +ENDCHAR +STARTCHAR plus +ENCODING 43 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +20 +20 +F8 +20 +20 +ENDCHAR +STARTCHAR comma +ENCODING 44 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 2 3 1 -2 +BITMAP +40 +40 +80 +ENDCHAR +STARTCHAR hyphen +ENCODING 45 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 0 3 +BITMAP +F0 +ENDCHAR +STARTCHAR period +ENCODING 46 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 1 1 0 +BITMAP +80 +ENDCHAR +STARTCHAR slash +ENCODING 47 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 9 0 0 +BITMAP +10 +10 +20 +20 +40 +40 +40 +80 +80 +ENDCHAR +STARTCHAR zero +ENCODING 48 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +88 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR one +ENCODING 49 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 3 9 1 0 +BITMAP +20 +E0 +20 +20 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR two +ENCODING 50 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +08 +10 +20 +40 +80 +80 +F8 +ENDCHAR +STARTCHAR three +ENCODING 51 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +08 +30 +08 +08 +88 +88 +70 +ENDCHAR +STARTCHAR four +ENCODING 52 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +08 +18 +28 +28 +48 +88 +FC +08 +08 +ENDCHAR +STARTCHAR five +ENCODING 53 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +F8 +80 +80 +F0 +08 +08 +88 +88 +70 +ENDCHAR +STARTCHAR six +ENCODING 54 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +80 +B0 +C8 +88 +88 +88 +70 +ENDCHAR +STARTCHAR seven +ENCODING 55 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +F8 +08 +10 +10 +20 +20 +20 +40 +40 +ENDCHAR +STARTCHAR eight +ENCODING 56 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +88 +70 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR nine +ENCODING 57 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +88 +88 +78 +08 +08 +88 +70 +ENDCHAR +STARTCHAR colon +ENCODING 58 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 6 1 0 +BITMAP +80 +00 +00 +00 +00 +80 +ENDCHAR +STARTCHAR semicolon +ENCODING 59 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 8 0 -2 +BITMAP +40 +00 +00 +00 +00 +40 +40 +80 +ENDCHAR +STARTCHAR less +ENCODING 60 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 5 0 1 +BITMAP +0C +30 +C0 +30 +0C +ENDCHAR +STARTCHAR equal +ENCODING 61 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 3 1 2 +BITMAP +F8 +00 +F8 +ENDCHAR +STARTCHAR greater +ENCODING 62 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 5 1 1 +BITMAP +C0 +30 +0C +30 +C0 +ENDCHAR +STARTCHAR question +ENCODING 63 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +88 +10 +10 +20 +20 +00 +20 +ENDCHAR +STARTCHAR at +ENCODING 64 +SWIDTH 1015 0 +DWIDTH 12 0 +BBX 10 10 1 -1 +BITMAP +1F00 +6080 +4D40 +9240 +A240 +A240 +A680 +9B00 +4000 +3E00 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +10 +28 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +F8 +84 +84 +84 +F8 +84 +84 +84 +F8 +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +3C +42 +80 +80 +80 +80 +80 +42 +3C +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +F8 +84 +82 +82 +82 +82 +82 +84 +F8 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +FC +80 +80 +80 +F8 +80 +80 +80 +80 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +3C +42 +80 +80 +8E +82 +82 +46 +3A +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +82 +82 +82 +82 +FE +82 +82 +82 +82 +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 9 1 0 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +08 +08 +08 +08 +08 +08 +88 +88 +70 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 9 1 0 +BITMAP +84 +88 +90 +A0 +E0 +90 +88 +84 +82 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +F8 +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 833 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +8080 +C180 +C180 +A280 +A280 +9480 +9480 +8880 +8880 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +82 +C2 +A2 +A2 +92 +8A +8A +86 +82 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +F8 +84 +84 +84 +F8 +80 +80 +80 +80 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +3C +42 +81 +81 +81 +89 +85 +42 +3D +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +F8 +84 +84 +84 +F8 +88 +84 +84 +84 +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +78 +84 +80 +60 +18 +04 +84 +84 +78 +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +FE +10 +10 +10 +10 +10 +10 +10 +10 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +82 +82 +44 +44 +44 +28 +28 +10 +10 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 944 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +8880 +8880 +8880 +4900 +5500 +5500 +2200 +2200 +2200 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +82 +44 +44 +28 +10 +28 +44 +44 +82 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +82 +82 +44 +44 +28 +10 +10 +10 +10 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 611 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +FE +02 +04 +08 +10 +20 +40 +80 +FE +ENDCHAR +STARTCHAR bracketleft +ENCODING 91 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 12 1 -3 +BITMAP +C0 +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +C0 +ENDCHAR +STARTCHAR backslash +ENCODING 92 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 4 9 0 0 +BITMAP +80 +80 +40 +40 +20 +20 +20 +10 +10 +ENDCHAR +STARTCHAR bracketright +ENCODING 93 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 12 0 -3 +BITMAP +C0 +40 +40 +40 +40 +40 +40 +40 +40 +40 +40 +C0 +ENDCHAR +STARTCHAR asciicircum +ENCODING 94 +SWIDTH 469 0 +DWIDTH 6 0 +BBX 5 3 0 5 +BITMAP +20 +50 +88 +ENDCHAR +STARTCHAR underscore +ENCODING 95 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 1 0 -2 +BITMAP +FE +ENDCHAR +STARTCHAR grave +ENCODING 96 +SWIDTH 333 0 +DWIDTH 2 0 +BBX 2 2 0 8 +BITMAP +80 +40 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 1 0 +BITMAP +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +80 +80 +B0 +C8 +88 +88 +88 +C8 +B0 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +70 +88 +80 +80 +80 +88 +70 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +08 +08 +68 +98 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 9 0 0 +BITMAP +30 +40 +E0 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +68 +98 +88 +88 +88 +98 +68 +08 +88 +70 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +80 +80 +B0 +C8 +88 +88 +88 +88 +88 +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 1 9 1 0 +BITMAP +80 +00 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 2 12 0 -3 +BITMAP +40 +00 +40 +40 +40 +40 +40 +40 +40 +40 +40 +80 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 9 1 0 +BITMAP +80 +80 +90 +A0 +C0 +C0 +A0 +90 +88 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 1 9 1 0 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 833 0 +DWIDTH 9 0 +BBX 7 7 1 0 +BITMAP +A4 +DA +92 +92 +92 +92 +92 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +B0 +C8 +88 +88 +88 +88 +88 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +B0 +C8 +88 +88 +88 +C8 +B0 +80 +80 +80 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +68 +98 +88 +88 +88 +98 +68 +08 +08 +08 +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 7 1 0 +BITMAP +A0 +C0 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 7 1 0 +BITMAP +60 +90 +80 +60 +10 +90 +60 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 0 0 +BITMAP +40 +40 +E0 +40 +40 +40 +40 +40 +60 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +88 +88 +88 +50 +50 +20 +20 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 7 0 0 +BITMAP +8880 +8880 +4900 +4900 +5500 +2200 +2200 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 6 7 0 0 +BITMAP +84 +48 +30 +30 +48 +84 +84 +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +88 +88 +88 +90 +50 +50 +20 +20 +40 +80 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 7 1 0 +BITMAP +F0 +10 +20 +40 +40 +80 +F0 +ENDCHAR +STARTCHAR braceleft +ENCODING 123 +SWIDTH 334 0 +DWIDTH 4 0 +BBX 4 12 0 -3 +BITMAP +30 +40 +40 +40 +40 +80 +40 +40 +40 +40 +40 +30 +ENDCHAR +STARTCHAR bar +ENCODING 124 +SWIDTH 260 0 +DWIDTH 3 0 +BBX 1 12 1 -3 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR braceright +ENCODING 125 +SWIDTH 334 0 +DWIDTH 4 0 +BBX 4 12 0 -3 +BITMAP +C0 +20 +20 +20 +20 +10 +20 +20 +20 +20 +20 +C0 +ENDCHAR +STARTCHAR asciitilde +ENCODING 126 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 2 0 3 +BITMAP +64 +98 +ENDCHAR +STARTCHAR space +ENCODING 160 +SWIDTH 278 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR exclamdown +ENCODING 161 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 1 10 1 -3 +BITMAP +80 +00 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR cent +ENCODING 162 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 -1 +BITMAP +10 +70 +A8 +A0 +A0 +A0 +C8 +70 +40 +ENDCHAR +STARTCHAR sterling +ENCODING 163 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +30 +48 +40 +40 +F0 +20 +20 +48 +B0 +ENDCHAR +STARTCHAR currency +ENCODING 164 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 6 0 1 +BITMAP +84 +78 +48 +48 +78 +84 +ENDCHAR +STARTCHAR yen +ENCODING 165 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +88 +88 +50 +20 +F8 +20 +F8 +20 +20 +ENDCHAR +STARTCHAR brokenbar +ENCODING 166 +SWIDTH 260 0 +DWIDTH 3 0 +BBX 1 11 1 -2 +BITMAP +80 +80 +80 +80 +00 +00 +00 +80 +80 +80 +80 +ENDCHAR +STARTCHAR section +ENCODING 167 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 5 12 0 -3 +BITMAP +70 +88 +80 +60 +90 +88 +88 +48 +30 +08 +88 +70 +ENDCHAR +STARTCHAR dieresis +ENCODING 168 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 1 0 8 +BITMAP +A0 +ENDCHAR +STARTCHAR copyright +ENCODING 169 +SWIDTH 737 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +3E00 +4100 +9C80 +A280 +A080 +A280 +9C80 +4100 +3E00 +ENDCHAR +STARTCHAR ordfeminine +ENCODING 170 +SWIDTH 370 0 +DWIDTH 5 0 +BBX 3 5 1 4 +BITMAP +E0 +20 +A0 +00 +E0 +ENDCHAR +STARTCHAR guillemotleft +ENCODING 171 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +28 +50 +A0 +50 +28 +ENDCHAR +STARTCHAR logicalnot +ENCODING 172 +SWIDTH 584 0 +DWIDTH 8 0 +BBX 6 4 1 2 +BITMAP +FC +04 +04 +04 +ENDCHAR +STARTCHAR hyphen +ENCODING 173 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 0 3 +BITMAP +F0 +ENDCHAR +STARTCHAR registered +ENCODING 174 +SWIDTH 737 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +3E00 +4100 +9C80 +9480 +9880 +9480 +9480 +4100 +3E00 +ENDCHAR +STARTCHAR macron +ENCODING 175 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 1 0 8 +BITMAP +F0 +ENDCHAR +STARTCHAR degree +ENCODING 176 +SWIDTH 400 0 +DWIDTH 5 0 +BBX 4 4 0 4 +BITMAP +60 +90 +90 +60 +ENDCHAR +STARTCHAR plusminus +ENCODING 177 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +20 +20 +F8 +20 +20 +00 +F8 +ENDCHAR +STARTCHAR twosuperior +ENCODING 178 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 5 0 3 +BITMAP +60 +90 +20 +40 +F0 +ENDCHAR +STARTCHAR threesuperior +ENCODING 179 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 5 0 3 +BITMAP +E0 +20 +40 +20 +C0 +ENDCHAR +STARTCHAR acute +ENCODING 180 +SWIDTH 333 0 +DWIDTH 2 0 +BBX 2 2 0 8 +BITMAP +40 +80 +ENDCHAR +STARTCHAR mu +ENCODING 181 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +88 +88 +88 +88 +88 +98 +E8 +80 +80 +80 +ENDCHAR +STARTCHAR paragraph +ENCODING 182 +SWIDTH 537 0 +DWIDTH 7 0 +BBX 6 12 0 -3 +BITMAP +3C +68 +E8 +E8 +E8 +68 +28 +28 +28 +28 +28 +28 +ENDCHAR +STARTCHAR periodcentered +ENCODING 183 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 1 1 3 +BITMAP +80 +ENDCHAR +STARTCHAR cedilla +ENCODING 184 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 4 0 -3 +BITMAP +40 +20 +20 +C0 +ENDCHAR +STARTCHAR onesuperior +ENCODING 185 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 5 1 3 +BITMAP +40 +C0 +40 +40 +40 +ENDCHAR +STARTCHAR ordmasculine +ENCODING 186 +SWIDTH 365 0 +DWIDTH 5 0 +BBX 3 5 1 4 +BITMAP +E0 +A0 +E0 +00 +E0 +ENDCHAR +STARTCHAR guillemotright +ENCODING 187 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +A0 +50 +28 +50 +A0 +ENDCHAR +STARTCHAR onequarter +ENCODING 188 +SWIDTH 834 0 +DWIDTH 10 0 +BBX 9 9 0 0 +BITMAP +4100 +C200 +4400 +4400 +4900 +1300 +1500 +2780 +4100 +ENDCHAR +STARTCHAR onehalf +ENCODING 189 +SWIDTH 834 0 +DWIDTH 10 0 +BBX 9 9 0 0 +BITMAP +4100 +C200 +4400 +4800 +4B00 +1480 +1100 +2200 +4780 +ENDCHAR +STARTCHAR threequarters +ENCODING 190 +SWIDTH 834 0 +DWIDTH 10 0 +BBX 9 9 0 0 +BITMAP +E100 +2200 +4400 +2400 +C900 +0B00 +1500 +1780 +2100 +ENDCHAR +STARTCHAR questiondown +ENCODING 191 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 5 9 1 -3 +BITMAP +20 +00 +20 +20 +40 +40 +88 +88 +70 +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +20 +10 +00 +10 +10 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR Aacute +ENCODING 193 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +08 +10 +00 +10 +10 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR Acircumflex +ENCODING 194 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +10 +28 +00 +10 +10 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR Atilde +ENCODING 195 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +14 +28 +00 +10 +10 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR Adieresis +ENCODING 196 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +28 +00 +10 +10 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR Aring +ENCODING 197 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +10 +28 +10 +10 +10 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR AE +ENCODING 198 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +1F80 +2800 +2800 +4800 +4F80 +7800 +8800 +8800 +8F80 +ENDCHAR +STARTCHAR Ccedilla +ENCODING 199 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +3C +42 +80 +80 +80 +80 +80 +42 +3C +08 +08 +30 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +20 +10 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR Eacute +ENCODING 201 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +08 +10 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR Ecircumflex +ENCODING 202 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +10 +28 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR Edieresis +ENCODING 203 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +28 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR Igrave +ENCODING 204 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 12 0 0 +BITMAP +80 +40 +00 +40 +40 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR Iacute +ENCODING 205 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 12 1 0 +BITMAP +40 +80 +00 +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR Icircumflex +ENCODING 206 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 12 0 0 +BITMAP +40 +A0 +00 +40 +40 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR Idieresis +ENCODING 207 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 11 0 0 +BITMAP +A0 +00 +40 +40 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR Eth +ENCODING 208 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 9 0 0 +BITMAP +7C +42 +41 +41 +F1 +41 +41 +42 +7C +ENDCHAR +STARTCHAR Ntilde +ENCODING 209 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +14 +28 +00 +82 +C2 +A2 +A2 +92 +8A +8A +86 +82 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +10 +08 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR Oacute +ENCODING 211 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +04 +08 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR Ocircumflex +ENCODING 212 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +08 +14 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR Otilde +ENCODING 213 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +14 +28 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR Odieresis +ENCODING 214 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +24 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR multiply +ENCODING 215 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +88 +50 +20 +50 +88 +ENDCHAR +STARTCHAR Oslash +ENCODING 216 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 11 0 -1 +BITMAP +0040 +1E80 +2100 +4280 +4480 +4480 +4880 +5080 +2100 +5E00 +8000 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +20 +10 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR Uacute +ENCODING 218 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +08 +10 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR Ucircumflex +ENCODING 219 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +10 +28 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR Udieresis +ENCODING 220 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +48 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR Yacute +ENCODING 221 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +08 +10 +00 +82 +82 +44 +44 +28 +10 +10 +10 +10 +ENDCHAR +STARTCHAR Thorn +ENCODING 222 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +80 +80 +F8 +84 +84 +84 +F8 +80 +80 +ENDCHAR +STARTCHAR germandbls +ENCODING 223 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +88 +88 +B0 +88 +88 +88 +B0 +ENDCHAR +STARTCHAR agrave +ENCODING 224 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 1 0 +BITMAP +20 +10 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR aacute +ENCODING 225 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 1 0 +BITMAP +10 +20 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR acircumflex +ENCODING 226 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 1 0 +BITMAP +20 +50 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR atilde +ENCODING 227 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 1 0 +BITMAP +28 +50 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR adieresis +ENCODING 228 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +50 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR aring +ENCODING 229 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 1 0 +BITMAP +30 +48 +30 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR ae +ENCODING 230 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 9 7 1 0 +BITMAP +7700 +8880 +0880 +7F80 +8800 +8880 +7700 +ENDCHAR +STARTCHAR ccedilla +ENCODING 231 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +70 +88 +80 +80 +80 +88 +70 +20 +10 +60 +ENDCHAR +STARTCHAR egrave +ENCODING 232 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +40 +20 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR eacute +ENCODING 233 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +10 +20 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR ecircumflex +ENCODING 234 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +20 +50 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR edieresis +ENCODING 235 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +50 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR igrave +ENCODING 236 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 10 0 0 +BITMAP +80 +40 +00 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR iacute +ENCODING 237 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 10 1 0 +BITMAP +40 +80 +00 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR icircumflex +ENCODING 238 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 10 0 0 +BITMAP +40 +A0 +00 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR idieresis +ENCODING 239 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 0 0 +BITMAP +A0 +00 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR eth +ENCODING 240 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +68 +30 +50 +08 +78 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR ntilde +ENCODING 241 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +28 +50 +00 +B0 +C8 +88 +88 +88 +88 +88 +ENDCHAR +STARTCHAR ograve +ENCODING 242 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +40 +20 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR oacute +ENCODING 243 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +10 +20 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR ocircumflex +ENCODING 244 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +20 +50 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR otilde +ENCODING 245 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +28 +50 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR odieresis +ENCODING 246 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +50 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR divide +ENCODING 247 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 5 1 1 +BITMAP +20 +00 +F8 +00 +20 +ENDCHAR +STARTCHAR oslash +ENCODING 248 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 7 0 0 +BITMAP +3A +44 +4C +54 +64 +44 +B8 +ENDCHAR +STARTCHAR ugrave +ENCODING 249 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +40 +20 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR uacute +ENCODING 250 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +10 +20 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR ucircumflex +ENCODING 251 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +20 +50 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR udieresis +ENCODING 252 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +50 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR yacute +ENCODING 253 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 13 1 -3 +BITMAP +10 +20 +00 +88 +88 +88 +90 +50 +50 +20 +20 +40 +80 +ENDCHAR +STARTCHAR thorn +ENCODING 254 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 -3 +BITMAP +80 +80 +B0 +C8 +88 +88 +88 +C8 +B0 +80 +80 +80 +ENDCHAR +STARTCHAR ydieresis +ENCODING 255 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 12 1 -3 +BITMAP +50 +00 +88 +88 +48 +50 +50 +30 +20 +20 +20 +C0 +ENDCHAR +STARTCHAR Amacron +ENCODING 256 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +3C +00 +10 +28 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR amacron +ENCODING 257 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +78 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR Abreve +ENCODING 258 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +24 +18 +00 +10 +28 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR abreve +ENCODING 259 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 1 0 +BITMAP +48 +30 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR Aogonek +ENCODING 260 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +10 +28 +28 +44 +44 +7C +82 +82 +92 +20 +20 +18 +ENDCHAR +STARTCHAR aogonek +ENCODING 261 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 1 -3 +BITMAP +70 +88 +08 +78 +88 +88 +74 +20 +20 +18 +ENDCHAR +STARTCHAR Cacute +ENCODING 262 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +08 +10 +00 +3C +42 +80 +80 +80 +80 +80 +42 +3C +ENDCHAR +STARTCHAR cacute +ENCODING 263 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +10 +20 +00 +70 +88 +80 +80 +80 +88 +70 +ENDCHAR +STARTCHAR Ccircumflex +ENCODING 264 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +10 +28 +00 +3C +42 +80 +80 +80 +80 +80 +42 +3C +ENDCHAR +STARTCHAR ccircumflex +ENCODING 265 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +20 +50 +00 +70 +88 +80 +80 +80 +88 +70 +ENDCHAR +STARTCHAR Cdotaccent +ENCODING 266 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +10 +00 +3C +42 +80 +80 +80 +80 +80 +42 +3C +ENDCHAR +STARTCHAR cdotaccent +ENCODING 267 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +20 +00 +70 +88 +80 +80 +80 +88 +70 +ENDCHAR +STARTCHAR Ccaron +ENCODING 268 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +28 +10 +00 +3C +42 +80 +80 +80 +80 +80 +42 +3C +ENDCHAR +STARTCHAR ccaron +ENCODING 269 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +50 +20 +00 +70 +88 +80 +80 +80 +88 +70 +ENDCHAR +STARTCHAR Dcaron +ENCODING 270 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +28 +10 +00 +F8 +84 +82 +82 +82 +82 +82 +84 +F8 +ENDCHAR +STARTCHAR dcaron +ENCODING 271 +SWIDTH 750 0 +DWIDTH 10 0 +BBX 9 9 1 0 +BITMAP +0980 +0880 +6900 +9800 +8800 +8800 +8800 +9800 +6800 +ENDCHAR +STARTCHAR Dcroat +ENCODING 272 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 9 0 0 +BITMAP +7C +42 +41 +41 +F1 +41 +41 +42 +7C +ENDCHAR +STARTCHAR dcroat +ENCODING 273 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +08 +38 +68 +98 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR Emacron +ENCODING 274 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +78 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR emacron +ENCODING 275 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +78 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR Ebreve +ENCODING 276 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +48 +30 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR ebreve +ENCODING 277 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +48 +30 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR Edotaccent +ENCODING 278 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +20 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR edotaccent +ENCODING 279 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +20 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR Eogonek +ENCODING 280 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 -3 +BITMAP +FC +80 +80 +80 +FC +80 +80 +80 +FC +40 +40 +30 +ENDCHAR +STARTCHAR eogonek +ENCODING 281 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +70 +88 +88 +F8 +80 +88 +70 +40 +40 +30 +ENDCHAR +STARTCHAR Ecaron +ENCODING 282 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +50 +20 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR ecaron +ENCODING 283 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +50 +20 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR Gcircumflex +ENCODING 284 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +10 +28 +00 +3C +42 +80 +80 +8E +82 +82 +46 +3A +ENDCHAR +STARTCHAR gcircumflex +ENCODING 285 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 13 1 -3 +BITMAP +20 +50 +00 +68 +98 +88 +88 +88 +98 +68 +08 +88 +70 +ENDCHAR +STARTCHAR Gbreve +ENCODING 286 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +24 +18 +00 +3C +42 +80 +80 +8E +82 +82 +46 +3A +ENDCHAR +STARTCHAR gbreve +ENCODING 287 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 13 1 -3 +BITMAP +48 +30 +00 +68 +98 +88 +88 +88 +98 +68 +08 +88 +70 +ENDCHAR +STARTCHAR Gdotaccent +ENCODING 288 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +10 +00 +3C +42 +80 +80 +8E +82 +82 +46 +3A +ENDCHAR +STARTCHAR gdotaccent +ENCODING 289 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 -3 +BITMAP +20 +00 +68 +98 +88 +88 +88 +98 +68 +08 +88 +70 +ENDCHAR +STARTCHAR Gcommaaccent +ENCODING 290 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 7 13 1 -4 +BITMAP +3C +42 +80 +80 +8E +82 +82 +46 +3A +00 +08 +08 +10 +ENDCHAR +STARTCHAR gcommaaccent +ENCODING 291 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 14 1 -3 +BITMAP +10 +20 +30 +00 +68 +98 +88 +88 +88 +98 +68 +08 +88 +70 +ENDCHAR +STARTCHAR Hcircumflex +ENCODING 292 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +10 +28 +00 +82 +82 +82 +82 +FE +82 +82 +82 +82 +ENDCHAR +STARTCHAR hcircumflex +ENCODING 293 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 0 +BITMAP +40 +A0 +00 +80 +80 +B0 +C8 +88 +88 +88 +88 +88 +ENDCHAR +STARTCHAR Hbar +ENCODING 294 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +82 +FE +82 +82 +FE +82 +82 +82 +82 +ENDCHAR +STARTCHAR hbar +ENCODING 295 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +80 +E0 +B0 +C8 +88 +88 +88 +88 +88 +ENDCHAR +STARTCHAR Itilde +ENCODING 296 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 12 0 0 +BITMAP +50 +A0 +00 +40 +40 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR itilde +ENCODING 297 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 10 0 0 +BITMAP +50 +A0 +00 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR Imacron +ENCODING 298 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 11 0 0 +BITMAP +F0 +00 +40 +40 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR imacron +ENCODING 299 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 9 0 0 +BITMAP +F0 +00 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR Ibreve +ENCODING 300 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 12 0 0 +BITMAP +90 +60 +00 +40 +40 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR ibreve +ENCODING 301 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 10 0 0 +BITMAP +90 +60 +00 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR Iogonek +ENCODING 302 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 12 0 -3 +BITMAP +40 +40 +40 +40 +40 +40 +40 +40 +40 +80 +80 +60 +ENDCHAR +STARTCHAR iogonek +ENCODING 303 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 3 12 0 -3 +BITMAP +40 +00 +40 +40 +40 +40 +40 +40 +40 +80 +80 +60 +ENDCHAR +STARTCHAR Idotaccent +ENCODING 304 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 11 1 0 +BITMAP +80 +00 +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR dotlessi +ENCODING 305 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 7 1 0 +BITMAP +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR IJ +ENCODING 306 +SWIDTH 764 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +81 +81 +81 +81 +81 +81 +91 +91 +8E +ENDCHAR +STARTCHAR ij +ENCODING 307 +SWIDTH 433 0 +DWIDTH 6 0 +BBX 4 12 1 -3 +BITMAP +90 +00 +90 +90 +90 +90 +90 +90 +90 +10 +10 +20 +ENDCHAR +STARTCHAR Jcircumflex +ENCODING 308 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 12 1 0 +BITMAP +10 +28 +00 +08 +08 +08 +08 +08 +08 +88 +88 +70 +ENDCHAR +STARTCHAR jcircumflex +ENCODING 309 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 3 13 0 -3 +BITMAP +40 +A0 +00 +40 +40 +40 +40 +40 +40 +40 +40 +40 +80 +ENDCHAR +STARTCHAR Kcommaaccent +ENCODING 310 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 13 1 -4 +BITMAP +84 +88 +90 +A0 +E0 +90 +88 +84 +82 +00 +10 +10 +20 +ENDCHAR +STARTCHAR kcommaaccent +ENCODING 311 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 13 1 -4 +BITMAP +80 +80 +90 +A0 +C0 +C0 +A0 +90 +88 +00 +20 +20 +40 +ENDCHAR +STARTCHAR kgreenlandic +ENCODING 312 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 7 1 0 +BITMAP +90 +A0 +C0 +C0 +A0 +90 +88 +ENDCHAR +STARTCHAR Lacute +ENCODING 313 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 0 +BITMAP +20 +40 +00 +80 +80 +80 +80 +80 +80 +80 +80 +F8 +ENDCHAR +STARTCHAR lacute +ENCODING 314 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 2 12 1 0 +BITMAP +40 +80 +00 +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR Lcommaaccent +ENCODING 315 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 13 1 -4 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +F8 +00 +20 +20 +40 +ENDCHAR +STARTCHAR lcommaaccent +ENCODING 316 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 2 13 0 -4 +BITMAP +40 +40 +40 +40 +40 +40 +40 +40 +40 +00 +40 +40 +80 +ENDCHAR +STARTCHAR Lcaron +ENCODING 317 +SWIDTH 750 0 +DWIDTH 10 0 +BBX 9 9 1 0 +BITMAP +8180 +8080 +8100 +8000 +8000 +8000 +8000 +8000 +F800 +ENDCHAR +STARTCHAR lcaron +ENCODING 318 +SWIDTH 433 0 +DWIDTH 6 0 +BBX 5 9 1 0 +BITMAP +98 +88 +90 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR Ldot +ENCODING 319 +SWIDTH 806 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +80 +80 +80 +80 +80 +81 +80 +80 +F8 +ENDCHAR +STARTCHAR ldot +ENCODING 320 +SWIDTH 489 0 +DWIDTH 6 0 +BBX 4 9 1 0 +BITMAP +80 +80 +80 +80 +80 +90 +80 +80 +80 +ENDCHAR +STARTCHAR Lslash +ENCODING 321 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 0 0 +BITMAP +40 +40 +50 +60 +C0 +40 +40 +40 +7C +ENDCHAR +STARTCHAR lslash +ENCODING 322 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 3 9 0 0 +BITMAP +40 +40 +40 +60 +C0 +40 +40 +40 +40 +ENDCHAR +STARTCHAR Nacute +ENCODING 323 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +08 +10 +00 +82 +C2 +A2 +A2 +92 +8A +8A +86 +82 +ENDCHAR +STARTCHAR nacute +ENCODING 324 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +10 +20 +00 +B0 +C8 +88 +88 +88 +88 +88 +ENDCHAR +STARTCHAR Ncommaaccent +ENCODING 325 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 13 1 -4 +BITMAP +82 +C2 +A2 +A2 +92 +8A +8A +86 +82 +00 +10 +10 +20 +ENDCHAR +STARTCHAR ncommaaccent +ENCODING 326 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 11 1 -4 +BITMAP +B0 +C8 +88 +88 +88 +88 +88 +00 +20 +20 +40 +ENDCHAR +STARTCHAR Ncaron +ENCODING 327 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +28 +10 +00 +82 +C2 +A2 +A2 +92 +8A +8A +86 +82 +ENDCHAR +STARTCHAR ncaron +ENCODING 328 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +50 +20 +00 +B0 +C8 +88 +88 +88 +88 +88 +ENDCHAR +STARTCHAR napostrophe +ENCODING 329 +SWIDTH 767 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +C0 +40 +96 +19 +11 +11 +11 +11 +11 +ENDCHAR +STARTCHAR Eng +ENCODING 330 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +82 +C2 +A2 +A2 +92 +8A +8A +86 +82 +02 +02 +04 +ENDCHAR +STARTCHAR eng +ENCODING 331 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +B0 +C8 +88 +88 +88 +88 +88 +08 +08 +10 +ENDCHAR +STARTCHAR Omacron +ENCODING 332 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +3C +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR omacron +ENCODING 333 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +78 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR Obreve +ENCODING 334 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +24 +18 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR obreve +ENCODING 335 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +48 +30 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR Ohungarumlaut +ENCODING 336 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +14 +28 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR ohungarumlaut +ENCODING 337 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +28 +50 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR OE +ENCODING 338 +SWIDTH 1000 0 +DWIDTH 12 0 +BBX 10 9 1 0 +BITMAP +3FC0 +4400 +8400 +8400 +87C0 +8400 +8400 +4400 +3FC0 +ENDCHAR +STARTCHAR oe +ENCODING 339 +SWIDTH 944 0 +DWIDTH 11 0 +BBX 9 7 1 0 +BITMAP +7700 +8880 +8880 +8F80 +8800 +8880 +7700 +ENDCHAR +STARTCHAR Racute +ENCODING 340 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +10 +20 +00 +F8 +84 +84 +84 +F8 +88 +84 +84 +84 +ENDCHAR +STARTCHAR racute +ENCODING 341 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 10 1 0 +BITMAP +20 +40 +00 +A0 +C0 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR Rcommaaccent +ENCODING 342 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 13 1 -4 +BITMAP +F8 +84 +84 +84 +F8 +88 +84 +84 +84 +00 +10 +10 +20 +ENDCHAR +STARTCHAR rcommaaccent +ENCODING 343 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 11 1 -4 +BITMAP +A0 +C0 +80 +80 +80 +80 +80 +00 +40 +40 +80 +ENDCHAR +STARTCHAR Rcaron +ENCODING 344 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +50 +20 +00 +F8 +84 +84 +84 +F8 +88 +84 +84 +84 +ENDCHAR +STARTCHAR rcaron +ENCODING 345 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 10 1 0 +BITMAP +A0 +40 +00 +A0 +C0 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR Sacute +ENCODING 346 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +10 +20 +00 +78 +84 +80 +60 +18 +04 +84 +84 +78 +ENDCHAR +STARTCHAR sacute +ENCODING 347 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 10 1 0 +BITMAP +20 +40 +00 +60 +90 +80 +60 +10 +90 +60 +ENDCHAR +STARTCHAR Scircumflex +ENCODING 348 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +20 +50 +00 +78 +84 +80 +60 +18 +04 +84 +84 +78 +ENDCHAR +STARTCHAR scircumflex +ENCODING 349 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 10 1 0 +BITMAP +20 +50 +00 +60 +90 +80 +60 +10 +90 +60 +ENDCHAR +STARTCHAR Scedilla +ENCODING 350 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 -3 +BITMAP +78 +84 +80 +60 +18 +04 +84 +84 +78 +10 +10 +60 +ENDCHAR +STARTCHAR scedilla +ENCODING 351 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 10 1 -3 +BITMAP +60 +90 +80 +60 +10 +90 +60 +20 +20 +C0 +ENDCHAR +STARTCHAR Scaron +ENCODING 352 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +28 +10 +00 +78 +84 +80 +60 +18 +04 +84 +84 +78 +ENDCHAR +STARTCHAR scaron +ENCODING 353 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 10 1 0 +BITMAP +A0 +40 +00 +60 +90 +80 +60 +10 +90 +60 +ENDCHAR +STARTCHAR Tcommaaccent +ENCODING 354 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 12 0 -3 +BITMAP +FE +10 +10 +10 +10 +10 +10 +10 +10 +08 +08 +30 +ENDCHAR +STARTCHAR tcommaaccent +ENCODING 355 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 12 0 -3 +BITMAP +40 +40 +E0 +40 +40 +40 +40 +40 +60 +20 +20 +C0 +ENDCHAR +STARTCHAR Tcaron +ENCODING 356 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 12 0 0 +BITMAP +28 +10 +00 +FE +10 +10 +10 +10 +10 +10 +10 +10 +ENDCHAR +STARTCHAR tcaron +ENCODING 357 +SWIDTH 486 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +4C +44 +E8 +40 +40 +40 +40 +40 +60 +ENDCHAR +STARTCHAR Tbar +ENCODING 358 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 9 0 0 +BITMAP +FE +10 +10 +10 +38 +10 +10 +10 +10 +ENDCHAR +STARTCHAR tbar +ENCODING 359 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 0 0 +BITMAP +40 +40 +E0 +40 +40 +E0 +40 +40 +60 +ENDCHAR +STARTCHAR Utilde +ENCODING 360 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +28 +50 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR utilde +ENCODING 361 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +28 +50 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR Umacron +ENCODING 362 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +78 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR umacron +ENCODING 363 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +78 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR Ubreve +ENCODING 364 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +48 +30 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR ubreve +ENCODING 365 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +48 +30 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR Uring +ENCODING 366 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 13 1 0 +BITMAP +30 +48 +30 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR uring +ENCODING 367 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 11 1 0 +BITMAP +30 +48 +30 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR Uhungarumlaut +ENCODING 368 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +28 +50 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR uhungarumlaut +ENCODING 369 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +28 +50 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR Uogonek +ENCODING 370 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 -3 +BITMAP +84 +84 +84 +84 +84 +84 +84 +84 +78 +20 +20 +18 +ENDCHAR +STARTCHAR uogonek +ENCODING 371 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +88 +88 +88 +88 +88 +98 +78 +20 +20 +18 +ENDCHAR +STARTCHAR Wcircumflex +ENCODING 372 +SWIDTH 944 0 +DWIDTH 11 0 +BBX 9 12 1 0 +BITMAP +0800 +1400 +0000 +8880 +8880 +8880 +4900 +5500 +5500 +2200 +2200 +2200 +ENDCHAR +STARTCHAR wcircumflex +ENCODING 373 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 10 0 0 +BITMAP +0800 +1400 +0000 +8880 +8880 +4900 +4900 +5500 +2200 +2200 +ENDCHAR +STARTCHAR Ycircumflex +ENCODING 374 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +10 +28 +00 +82 +82 +44 +44 +28 +10 +10 +10 +10 +ENDCHAR +STARTCHAR ycircumflex +ENCODING 375 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 13 1 -3 +BITMAP +20 +50 +00 +88 +88 +88 +90 +50 +50 +20 +20 +40 +80 +ENDCHAR +STARTCHAR Ydieresis +ENCODING 376 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +28 +00 +82 +82 +44 +44 +28 +10 +10 +10 +10 +ENDCHAR +STARTCHAR Zacute +ENCODING 377 +SWIDTH 611 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +08 +10 +00 +FE +02 +04 +08 +10 +20 +40 +80 +FE +ENDCHAR +STARTCHAR zacute +ENCODING 378 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 10 1 0 +BITMAP +10 +20 +00 +F0 +10 +20 +40 +40 +80 +F0 +ENDCHAR +STARTCHAR Zdotaccent +ENCODING 379 +SWIDTH 611 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +10 +00 +FE +02 +04 +08 +10 +20 +40 +80 +FE +ENDCHAR +STARTCHAR zdotaccent +ENCODING 380 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 9 1 0 +BITMAP +20 +00 +F0 +10 +20 +40 +40 +80 +F0 +ENDCHAR +STARTCHAR Zcaron +ENCODING 381 +SWIDTH 611 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +28 +10 +00 +FE +02 +04 +08 +10 +20 +40 +80 +FE +ENDCHAR +STARTCHAR zcaron +ENCODING 382 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 10 0 0 +BITMAP +50 +20 +00 +F8 +08 +10 +20 +40 +80 +F8 +ENDCHAR +STARTCHAR uni0186 +ENCODING 390 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +78 +84 +02 +02 +02 +02 +02 +84 +78 +ENDCHAR +STARTCHAR uni0189 +ENCODING 393 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 9 0 0 +BITMAP +7C +42 +41 +41 +F1 +41 +41 +42 +7C +ENDCHAR +STARTCHAR uni018E +ENCODING 398 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +FC +04 +04 +04 +FC +04 +04 +04 +FC +ENDCHAR +STARTCHAR florin +ENCODING 402 +SWIDTH 556 0 +DWIDTH 6 0 +BBX 4 11 1 -2 +BITMAP +30 +40 +40 +E0 +40 +40 +40 +40 +40 +40 +80 +ENDCHAR +STARTCHAR uni0197 +ENCODING 407 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 0 0 +BITMAP +40 +40 +40 +40 +E0 +40 +40 +40 +40 +ENDCHAR +STARTCHAR uni019A +ENCODING 410 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 3 9 0 0 +BITMAP +40 +40 +40 +40 +E0 +40 +40 +40 +40 +ENDCHAR +STARTCHAR uni019D +ENCODING 413 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 12 0 -3 +BITMAP +41 +61 +51 +51 +49 +45 +45 +43 +41 +40 +40 +80 +ENDCHAR +STARTCHAR uni019F +ENCODING 415 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 9 1 0 +BITMAP +3C +42 +81 +81 +FF +81 +81 +42 +3C +ENDCHAR +STARTCHAR Ohorn +ENCODING 416 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 9 1 0 +BITMAP +3CC0 +4240 +8180 +8100 +8100 +8100 +8100 +4200 +3C00 +ENDCHAR +STARTCHAR ohorn +ENCODING 417 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 7 1 0 +BITMAP +76 +8A +8C +88 +88 +88 +70 +ENDCHAR +STARTCHAR uni01A7 +ENCODING 423 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +78 +84 +04 +18 +60 +80 +84 +84 +78 +ENDCHAR +STARTCHAR uni01A8 +ENCODING 424 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 7 1 0 +BITMAP +60 +90 +10 +60 +80 +90 +60 +ENDCHAR +STARTCHAR uni01AE +ENCODING 430 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 12 0 -3 +BITMAP +FE +10 +10 +10 +10 +10 +10 +10 +10 +10 +10 +08 +ENDCHAR +STARTCHAR Uhorn +ENCODING 431 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 9 1 0 +BITMAP +87 +85 +86 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR uhorn +ENCODING 432 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 7 1 0 +BITMAP +8E +8A +8C +88 +88 +98 +68 +ENDCHAR +STARTCHAR uni01B5 +ENCODING 437 +SWIDTH 611 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +FE +02 +04 +08 +38 +20 +40 +80 +FE +ENDCHAR +STARTCHAR uni01B6 +ENCODING 438 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 7 1 0 +BITMAP +F0 +10 +20 +70 +40 +80 +F0 +ENDCHAR +STARTCHAR uni01BB +ENCODING 443 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +70 +88 +08 +10 +F8 +40 +80 +80 +F8 +ENDCHAR +STARTCHAR uni01BC +ENCODING 444 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +F8 +80 +80 +F0 +08 +08 +88 +88 +70 +ENDCHAR +STARTCHAR uni01C0 +ENCODING 448 +SWIDTH 260 0 +DWIDTH 3 0 +BBX 1 12 1 -3 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR uni01C2 +ENCODING 450 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 12 1 -2 +BITMAP +20 +20 +20 +20 +20 +F8 +20 +F8 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni01C3 +ENCODING 451 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 9 1 0 +BITMAP +80 +80 +80 +80 +80 +80 +80 +00 +80 +ENDCHAR +STARTCHAR uni01CD +ENCODING 461 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +28 +10 +00 +10 +28 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR uni01CE +ENCODING 462 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 1 0 +BITMAP +50 +20 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR uni01CF +ENCODING 463 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 12 0 0 +BITMAP +A0 +40 +00 +40 +40 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR uni01D0 +ENCODING 464 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 10 0 0 +BITMAP +A0 +40 +00 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR uni01D1 +ENCODING 465 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +14 +08 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR uni01D2 +ENCODING 466 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +50 +20 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR uni01D3 +ENCODING 467 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +28 +10 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR uni01D4 +ENCODING 468 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +50 +20 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR uni01D5 +ENCODING 469 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 13 1 0 +BITMAP +78 +00 +48 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR uni01D6 +ENCODING 470 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 11 1 0 +BITMAP +78 +00 +50 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR uni01D7 +ENCODING 471 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 14 1 0 +BITMAP +10 +20 +00 +48 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR uni01D8 +ENCODING 472 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 0 +BITMAP +10 +20 +00 +50 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR uni01D9 +ENCODING 473 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 14 1 0 +BITMAP +28 +10 +00 +48 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR uni01DA +ENCODING 474 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 0 +BITMAP +50 +20 +00 +50 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR uni01DB +ENCODING 475 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 14 1 0 +BITMAP +20 +10 +00 +48 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR uni01DC +ENCODING 476 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 0 +BITMAP +40 +20 +00 +50 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR uni01DD +ENCODING 477 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +70 +88 +08 +F8 +88 +88 +70 +ENDCHAR +STARTCHAR uni01DE +ENCODING 478 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +3C +00 +28 +00 +10 +10 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR uni01DF +ENCODING 479 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 11 1 0 +BITMAP +78 +00 +50 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR uni01E0 +ENCODING 480 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 13 1 0 +BITMAP +3C +00 +10 +00 +10 +28 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR uni01E1 +ENCODING 481 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 11 1 0 +BITMAP +78 +00 +20 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR uni01E2 +ENCODING 482 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 9 11 1 0 +BITMAP +1E00 +0000 +1F80 +2800 +2800 +4800 +4F80 +7800 +8800 +8800 +8F80 +ENDCHAR +STARTCHAR uni01E3 +ENCODING 483 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +1E00 +0000 +7700 +8880 +0880 +7F80 +8800 +8880 +7700 +ENDCHAR +STARTCHAR uni01E4 +ENCODING 484 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +3C +42 +80 +80 +8E +8E +82 +46 +3A +ENDCHAR +STARTCHAR uni01E5 +ENCODING 485 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +68 +98 +88 +88 +88 +98 +68 +F8 +88 +70 +ENDCHAR +STARTCHAR Gcaron +ENCODING 486 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +28 +10 +00 +3C +42 +80 +80 +8E +82 +82 +46 +3A +ENDCHAR +STARTCHAR gcaron +ENCODING 487 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 13 1 -3 +BITMAP +50 +20 +00 +68 +98 +88 +88 +88 +98 +68 +08 +88 +70 +ENDCHAR +STARTCHAR uni01E8 +ENCODING 488 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 12 1 0 +BITMAP +50 +20 +00 +84 +88 +90 +A0 +E0 +90 +88 +84 +82 +ENDCHAR +STARTCHAR uni01E9 +ENCODING 489 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 12 1 0 +BITMAP +A0 +40 +00 +80 +80 +90 +A0 +C0 +C0 +A0 +90 +88 +ENDCHAR +STARTCHAR uni01EA +ENCODING 490 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 -3 +BITMAP +3C +42 +81 +81 +81 +81 +81 +42 +3C +10 +10 +0C +ENDCHAR +STARTCHAR uni01EB +ENCODING 491 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +70 +88 +88 +88 +88 +88 +70 +40 +40 +30 +ENDCHAR +STARTCHAR uni01EC +ENCODING 492 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 14 1 -3 +BITMAP +3C +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +10 +10 +0C +ENDCHAR +STARTCHAR uni01ED +ENCODING 493 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 -3 +BITMAP +78 +00 +70 +88 +88 +88 +88 +88 +70 +40 +40 +30 +ENDCHAR +STARTCHAR uni01F0 +ENCODING 496 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 3 13 0 -3 +BITMAP +A0 +40 +00 +40 +40 +40 +40 +40 +40 +40 +40 +40 +80 +ENDCHAR +STARTCHAR uni01F4 +ENCODING 500 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +08 +10 +00 +3C +42 +80 +80 +8E +82 +82 +46 +3A +ENDCHAR +STARTCHAR uni01F5 +ENCODING 501 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 13 1 -3 +BITMAP +10 +20 +00 +68 +98 +88 +88 +88 +98 +68 +08 +88 +70 +ENDCHAR +STARTCHAR uni01F8 +ENCODING 504 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +20 +10 +00 +82 +C2 +A2 +A2 +92 +8A +8A +86 +82 +ENDCHAR +STARTCHAR uni01F9 +ENCODING 505 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +40 +20 +00 +B0 +C8 +88 +88 +88 +88 +88 +ENDCHAR +STARTCHAR Aringacute +ENCODING 506 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 15 1 0 +BITMAP +08 +10 +00 +10 +28 +10 +10 +10 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR aringacute +ENCODING 507 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 13 1 0 +BITMAP +10 +20 +00 +30 +48 +30 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR AEacute +ENCODING 508 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 9 12 1 0 +BITMAP +0400 +0800 +0000 +1F80 +2800 +2800 +4800 +4F80 +7800 +8800 +8800 +8F80 +ENDCHAR +STARTCHAR aeacute +ENCODING 509 +SWIDTH 889 0 +DWIDTH 11 0 +BBX 9 10 1 0 +BITMAP +0400 +0800 +0000 +7700 +8880 +0880 +7F80 +8800 +8880 +7700 +ENDCHAR +STARTCHAR Oslashacute +ENCODING 510 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 14 0 -1 +BITMAP +0200 +0400 +0000 +0040 +1E80 +2100 +4280 +4480 +4480 +4880 +5080 +2100 +5E00 +8000 +ENDCHAR +STARTCHAR oslashacute +ENCODING 511 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 10 0 0 +BITMAP +08 +10 +00 +3A +44 +4C +54 +64 +44 +B8 +ENDCHAR +STARTCHAR uni0200 +ENCODING 512 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +50 +28 +00 +10 +28 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR uni0201 +ENCODING 513 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 1 0 +BITMAP +A0 +50 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR uni0202 +ENCODING 514 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +18 +24 +00 +10 +28 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR uni0203 +ENCODING 515 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 10 1 0 +BITMAP +30 +48 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR uni0204 +ENCODING 516 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +A0 +50 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR uni0205 +ENCODING 517 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +A0 +50 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR uni0206 +ENCODING 518 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +30 +48 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR uni0207 +ENCODING 519 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +30 +48 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR uni0208 +ENCODING 520 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 12 -1 0 +BITMAP +A0 +50 +00 +20 +20 +20 +20 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni0209 +ENCODING 521 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 10 -1 0 +BITMAP +A0 +50 +00 +20 +20 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR uni020A +ENCODING 522 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 12 0 0 +BITMAP +60 +90 +00 +40 +40 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR uni020B +ENCODING 523 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 10 0 0 +BITMAP +60 +90 +00 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR uni020C +ENCODING 524 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +28 +14 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR uni020D +ENCODING 525 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +A0 +50 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR uni020E +ENCODING 526 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 12 1 0 +BITMAP +18 +24 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR uni020F +ENCODING 527 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +30 +48 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR uni0210 +ENCODING 528 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +A0 +50 +00 +F8 +84 +84 +84 +F8 +88 +84 +84 +84 +ENDCHAR +STARTCHAR uni0211 +ENCODING 529 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 10 0 0 +BITMAP +A0 +50 +00 +50 +60 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR uni0212 +ENCODING 530 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +30 +48 +00 +F8 +84 +84 +84 +F8 +88 +84 +84 +84 +ENDCHAR +STARTCHAR uni0213 +ENCODING 531 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 10 0 0 +BITMAP +60 +90 +00 +50 +60 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR uni0214 +ENCODING 532 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +50 +28 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR uni0215 +ENCODING 533 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +A0 +50 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR uni0216 +ENCODING 534 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +30 +48 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR uni0217 +ENCODING 535 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +30 +48 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR Scommaaccent +ENCODING 536 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 13 1 -4 +BITMAP +78 +84 +80 +60 +18 +04 +84 +84 +78 +00 +10 +10 +20 +ENDCHAR +STARTCHAR scommaaccent +ENCODING 537 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 11 1 -4 +BITMAP +60 +90 +80 +60 +10 +90 +60 +00 +20 +20 +40 +ENDCHAR +STARTCHAR Tcommaaccent +ENCODING 538 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 13 0 -4 +BITMAP +FE +10 +10 +10 +10 +10 +10 +10 +10 +00 +10 +10 +20 +ENDCHAR +STARTCHAR tcommaaccent +ENCODING 539 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 13 0 -4 +BITMAP +40 +40 +E0 +40 +40 +40 +40 +40 +60 +00 +40 +40 +80 +ENDCHAR +STARTCHAR uni021E +ENCODING 542 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +28 +10 +00 +82 +82 +82 +82 +FE +82 +82 +82 +82 +ENDCHAR +STARTCHAR uni021F +ENCODING 543 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 0 +BITMAP +A0 +40 +00 +80 +80 +B0 +C8 +88 +88 +88 +88 +88 +ENDCHAR +STARTCHAR uni0226 +ENCODING 550 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +10 +00 +10 +28 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR uni0227 +ENCODING 551 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 1 0 +BITMAP +20 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR uni0228 +ENCODING 552 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 -3 +BITMAP +FC +80 +80 +80 +FC +80 +80 +80 +FC +10 +10 +60 +ENDCHAR +STARTCHAR uni0229 +ENCODING 553 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +70 +88 +88 +F8 +80 +88 +70 +10 +10 +60 +ENDCHAR +STARTCHAR uni022A +ENCODING 554 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +3C +00 +24 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR uni022B +ENCODING 555 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 11 1 0 +BITMAP +78 +00 +50 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR uni022C +ENCODING 556 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +3C +00 +14 +28 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR uni022D +ENCODING 557 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 0 +BITMAP +78 +00 +28 +50 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR uni022E +ENCODING 558 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 11 1 0 +BITMAP +08 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR uni022F +ENCODING 559 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +20 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR uni0230 +ENCODING 560 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 13 1 0 +BITMAP +3C +00 +08 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR uni0231 +ENCODING 561 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 11 1 0 +BITMAP +78 +00 +20 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR uni0232 +ENCODING 562 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +3C +00 +82 +82 +44 +44 +28 +10 +10 +10 +10 +ENDCHAR +STARTCHAR uni0233 +ENCODING 563 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 12 1 -3 +BITMAP +78 +00 +88 +88 +88 +90 +50 +50 +20 +20 +40 +80 +ENDCHAR +STARTCHAR uni0250 +ENCODING 592 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 7 1 0 +BITMAP +B8 +44 +44 +78 +40 +44 +38 +ENDCHAR +STARTCHAR uni0254 +ENCODING 596 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +70 +88 +08 +08 +08 +88 +70 +ENDCHAR +STARTCHAR uni0258 +ENCODING 600 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +70 +88 +88 +F8 +08 +88 +70 +ENDCHAR +STARTCHAR uni0259 +ENCODING 601 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +70 +88 +08 +F8 +88 +88 +70 +ENDCHAR +STARTCHAR uni025F +ENCODING 607 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 9 0 -2 +BITMAP +20 +20 +20 +20 +20 +20 +70 +20 +C0 +ENDCHAR +STARTCHAR uni0265 +ENCODING 613 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 -2 +BITMAP +88 +88 +88 +88 +88 +98 +68 +08 +08 +ENDCHAR +STARTCHAR uni0275 +ENCODING 629 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +70 +88 +88 +F8 +88 +88 +70 +ENDCHAR +STARTCHAR uni0279 +ENCODING 633 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 7 1 0 +BITMAP +20 +20 +20 +20 +20 +60 +A0 +ENDCHAR +STARTCHAR uni0287 +ENCODING 647 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 9 0 0 +BITMAP +C0 +40 +40 +40 +40 +40 +E0 +40 +40 +ENDCHAR +STARTCHAR uni0288 +ENCODING 648 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 12 0 -3 +BITMAP +40 +40 +E0 +40 +40 +40 +40 +40 +40 +40 +40 +20 +ENDCHAR +STARTCHAR uni0289 +ENCODING 649 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +88 +88 +88 +F8 +88 +98 +68 +ENDCHAR +STARTCHAR uni028C +ENCODING 652 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 7 1 0 +BITMAP +20 +20 +50 +50 +88 +88 +88 +ENDCHAR +STARTCHAR uni028D +ENCODING 653 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 7 0 0 +BITMAP +2200 +2200 +5500 +4900 +4900 +8880 +8880 +ENDCHAR +STARTCHAR uni028E +ENCODING 654 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +08 +10 +20 +20 +50 +50 +48 +88 +88 +88 +ENDCHAR +STARTCHAR uni029E +ENCODING 670 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 9 1 -2 +BITMAP +88 +48 +28 +18 +18 +28 +48 +08 +08 +ENDCHAR +STARTCHAR uni02BB +ENCODING 699 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 2 3 0 6 +BITMAP +40 +80 +C0 +ENDCHAR +STARTCHAR afii57929 +ENCODING 700 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 2 3 1 6 +BITMAP +C0 +40 +80 +ENDCHAR +STARTCHAR afii64937 +ENCODING 701 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 2 3 1 6 +BITMAP +C0 +80 +40 +ENDCHAR +STARTCHAR circumflex +ENCODING 710 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 2 0 8 +BITMAP +40 +A0 +ENDCHAR +STARTCHAR caron +ENCODING 711 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 2 0 8 +BITMAP +A0 +40 +ENDCHAR +STARTCHAR uni02C8 +ENCODING 712 +SWIDTH 191 0 +DWIDTH 3 0 +BBX 1 3 1 6 +BITMAP +80 +80 +80 +ENDCHAR +STARTCHAR macron +ENCODING 713 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 1 0 8 +BITMAP +F0 +ENDCHAR +STARTCHAR uni02CA +ENCODING 714 +SWIDTH 333 0 +DWIDTH 2 0 +BBX 2 2 0 8 +BITMAP +40 +80 +ENDCHAR +STARTCHAR uni02CB +ENCODING 715 +SWIDTH 333 0 +DWIDTH 2 0 +BBX 2 2 0 8 +BITMAP +80 +40 +ENDCHAR +STARTCHAR uni02CD +ENCODING 717 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 1 0 -2 +BITMAP +F0 +ENDCHAR +STARTCHAR uni02CE +ENCODING 718 +SWIDTH 333 0 +DWIDTH 2 0 +BBX 2 2 0 -3 +BITMAP +80 +40 +ENDCHAR +STARTCHAR uni02CF +ENCODING 719 +SWIDTH 333 0 +DWIDTH 2 0 +BBX 2 2 0 -3 +BITMAP +40 +80 +ENDCHAR +STARTCHAR breve +ENCODING 728 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 2 0 8 +BITMAP +90 +60 +ENDCHAR +STARTCHAR dotaccent +ENCODING 729 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 1 1 1 8 +BITMAP +80 +ENDCHAR +STARTCHAR ring +ENCODING 730 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 3 0 7 +BITMAP +60 +90 +60 +ENDCHAR +STARTCHAR ogonek +ENCODING 731 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 4 0 -3 +BITMAP +40 +80 +80 +60 +ENDCHAR +STARTCHAR tilde +ENCODING 732 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 2 0 8 +BITMAP +50 +A0 +ENDCHAR +STARTCHAR hungarumlaut +ENCODING 733 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 2 0 8 +BITMAP +50 +A0 +ENDCHAR +STARTCHAR uni02EE +ENCODING 750 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 3 0 6 +BITMAP +D8 +48 +90 +ENDCHAR +STARTCHAR uni037E +ENCODING 894 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 2 8 0 -2 +BITMAP +40 +00 +00 +00 +00 +40 +40 +80 +ENDCHAR +STARTCHAR tonos +ENCODING 900 +SWIDTH 333 0 +DWIDTH 2 0 +BBX 2 2 0 8 +BITMAP +40 +80 +ENDCHAR +STARTCHAR dieresistonos +ENCODING 901 +SWIDTH 333 0 +DWIDTH 3 0 +BBX 3 4 0 8 +BITMAP +20 +40 +00 +A0 +ENDCHAR +STARTCHAR anoteleia +ENCODING 903 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 1 1 3 +BITMAP +80 +ENDCHAR +STARTCHAR mu +ENCODING 956 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +88 +88 +88 +88 +88 +98 +E8 +80 +80 +80 +ENDCHAR +STARTCHAR uni1E00 +ENCODING 7680 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 13 1 -4 +BITMAP +10 +28 +28 +44 +44 +7C +82 +82 +82 +00 +18 +24 +18 +ENDCHAR +STARTCHAR uni1E01 +ENCODING 7681 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 11 1 -4 +BITMAP +70 +88 +08 +78 +88 +88 +74 +00 +30 +48 +30 +ENDCHAR +STARTCHAR uni1E02 +ENCODING 7682 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +20 +00 +F8 +84 +84 +84 +F8 +84 +84 +84 +F8 +ENDCHAR +STARTCHAR uni1E03 +ENCODING 7683 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 11 1 0 +BITMAP +40 +00 +80 +80 +B0 +C8 +88 +88 +88 +C8 +B0 +ENDCHAR +STARTCHAR uni1E04 +ENCODING 7684 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 11 1 -2 +BITMAP +F8 +84 +84 +84 +F8 +84 +84 +84 +F8 +00 +20 +ENDCHAR +STARTCHAR uni1E05 +ENCODING 7685 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 11 1 -2 +BITMAP +80 +80 +B0 +C8 +88 +88 +88 +C8 +B0 +00 +20 +ENDCHAR +STARTCHAR uni1E06 +ENCODING 7686 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 11 1 -2 +BITMAP +F8 +84 +84 +84 +F8 +84 +84 +84 +F8 +00 +78 +ENDCHAR +STARTCHAR uni1E07 +ENCODING 7687 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 11 1 -2 +BITMAP +80 +80 +B0 +C8 +88 +88 +88 +C8 +B0 +00 +F0 +ENDCHAR +STARTCHAR uni1E08 +ENCODING 7688 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 15 1 -3 +BITMAP +08 +10 +00 +3C +42 +80 +80 +80 +80 +80 +42 +3C +08 +08 +30 +ENDCHAR +STARTCHAR uni1E09 +ENCODING 7689 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 13 1 -3 +BITMAP +10 +20 +00 +70 +88 +80 +80 +80 +88 +70 +20 +10 +60 +ENDCHAR +STARTCHAR uni1E0A +ENCODING 7690 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +10 +00 +F8 +84 +82 +82 +82 +82 +82 +84 +F8 +ENDCHAR +STARTCHAR uni1E0B +ENCODING 7691 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 11 1 0 +BITMAP +10 +00 +08 +08 +68 +98 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR uni1E0C +ENCODING 7692 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +F8 +84 +82 +82 +82 +82 +82 +84 +F8 +00 +10 +ENDCHAR +STARTCHAR uni1E0D +ENCODING 7693 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 11 1 -2 +BITMAP +08 +08 +68 +98 +88 +88 +88 +98 +68 +00 +20 +ENDCHAR +STARTCHAR uni1E0E +ENCODING 7694 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +F8 +84 +82 +82 +82 +82 +82 +84 +F8 +00 +78 +ENDCHAR +STARTCHAR uni1E0F +ENCODING 7695 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 11 1 -2 +BITMAP +08 +08 +68 +98 +88 +88 +88 +98 +68 +00 +78 +ENDCHAR +STARTCHAR uni1E10 +ENCODING 7696 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +F8 +84 +82 +82 +82 +82 +82 +84 +F8 +10 +10 +60 +ENDCHAR +STARTCHAR uni1E11 +ENCODING 7697 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 -3 +BITMAP +08 +08 +68 +98 +88 +88 +88 +98 +68 +10 +10 +60 +ENDCHAR +STARTCHAR uni1E12 +ENCODING 7698 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +F8 +84 +82 +82 +82 +82 +82 +84 +F8 +00 +10 +28 +ENDCHAR +STARTCHAR uni1E13 +ENCODING 7699 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 -3 +BITMAP +08 +08 +68 +98 +88 +88 +88 +98 +68 +00 +20 +50 +ENDCHAR +STARTCHAR uni1E14 +ENCODING 7700 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 14 1 0 +BITMAP +20 +10 +00 +78 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR uni1E15 +ENCODING 7701 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 0 +BITMAP +40 +20 +00 +78 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR uni1E16 +ENCODING 7702 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 14 1 0 +BITMAP +10 +20 +00 +78 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR uni1E17 +ENCODING 7703 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 0 +BITMAP +10 +20 +00 +78 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR uni1E18 +ENCODING 7704 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 -3 +BITMAP +FC +80 +80 +80 +FC +80 +80 +80 +FC +00 +20 +50 +ENDCHAR +STARTCHAR uni1E19 +ENCODING 7705 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +70 +88 +88 +F8 +80 +88 +70 +00 +20 +50 +ENDCHAR +STARTCHAR uni1E1A +ENCODING 7706 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 -3 +BITMAP +FC +80 +80 +80 +FC +80 +80 +80 +FC +00 +50 +A0 +ENDCHAR +STARTCHAR uni1E1B +ENCODING 7707 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +70 +88 +88 +F8 +80 +88 +70 +00 +50 +A0 +ENDCHAR +STARTCHAR uni1E1C +ENCODING 7708 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 15 1 -3 +BITMAP +90 +60 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +10 +10 +60 +ENDCHAR +STARTCHAR uni1E1D +ENCODING 7709 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 13 1 -3 +BITMAP +48 +30 +00 +70 +88 +88 +F8 +80 +88 +70 +10 +10 +60 +ENDCHAR +STARTCHAR uni1E1E +ENCODING 7710 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +20 +00 +FC +80 +80 +80 +F8 +80 +80 +80 +80 +ENDCHAR +STARTCHAR uni1E1F +ENCODING 7711 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 11 0 0 +BITMAP +20 +00 +30 +40 +E0 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR uni1E20 +ENCODING 7712 +SWIDTH 778 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +3C +00 +3C +42 +80 +80 +8E +82 +82 +46 +3A +ENDCHAR +STARTCHAR uni1E21 +ENCODING 7713 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 -3 +BITMAP +78 +00 +68 +98 +88 +88 +88 +98 +68 +08 +88 +70 +ENDCHAR +STARTCHAR uni1E22 +ENCODING 7714 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +10 +00 +82 +82 +82 +82 +FE +82 +82 +82 +82 +ENDCHAR +STARTCHAR uni1E23 +ENCODING 7715 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 11 1 0 +BITMAP +40 +00 +80 +80 +B0 +C8 +88 +88 +88 +88 +88 +ENDCHAR +STARTCHAR uni1E24 +ENCODING 7716 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +82 +82 +82 +82 +FE +82 +82 +82 +82 +00 +10 +ENDCHAR +STARTCHAR uni1E25 +ENCODING 7717 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 11 1 -2 +BITMAP +80 +80 +B0 +C8 +88 +88 +88 +88 +88 +00 +20 +ENDCHAR +STARTCHAR uni1E26 +ENCODING 7718 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +28 +00 +82 +82 +82 +82 +FE +82 +82 +82 +82 +ENDCHAR +STARTCHAR uni1E27 +ENCODING 7719 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 11 1 0 +BITMAP +A0 +00 +80 +80 +B0 +C8 +88 +88 +88 +88 +88 +ENDCHAR +STARTCHAR uni1E28 +ENCODING 7720 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +82 +82 +82 +82 +FE +82 +82 +82 +92 +08 +08 +30 +ENDCHAR +STARTCHAR uni1E29 +ENCODING 7721 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 -3 +BITMAP +80 +80 +B0 +C8 +88 +88 +88 +88 +A8 +10 +10 +60 +ENDCHAR +STARTCHAR uni1E2A +ENCODING 7722 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +82 +82 +82 +82 +FE +82 +82 +82 +82 +00 +24 +18 +ENDCHAR +STARTCHAR uni1E2B +ENCODING 7723 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 -3 +BITMAP +80 +80 +B0 +C8 +88 +88 +88 +88 +88 +00 +48 +30 +ENDCHAR +STARTCHAR uni1E2C +ENCODING 7724 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 12 -1 -3 +BITMAP +20 +20 +20 +20 +20 +20 +20 +20 +20 +00 +50 +A0 +ENDCHAR +STARTCHAR uni1E2D +ENCODING 7725 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 4 12 -1 -3 +BITMAP +20 +00 +20 +20 +20 +20 +20 +20 +20 +00 +50 +A0 +ENDCHAR +STARTCHAR uni1E2E +ENCODING 7726 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 14 0 0 +BITMAP +20 +40 +00 +A0 +00 +40 +40 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR uni1E2F +ENCODING 7727 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 12 0 0 +BITMAP +20 +40 +00 +A0 +00 +40 +40 +40 +40 +40 +40 +40 +ENDCHAR +STARTCHAR uni1E30 +ENCODING 7728 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 12 1 0 +BITMAP +10 +20 +00 +84 +88 +90 +A0 +E0 +90 +88 +84 +82 +ENDCHAR +STARTCHAR uni1E31 +ENCODING 7729 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 12 1 0 +BITMAP +20 +40 +00 +80 +80 +90 +A0 +C0 +C0 +A0 +90 +88 +ENDCHAR +STARTCHAR uni1E32 +ENCODING 7730 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 11 1 -2 +BITMAP +84 +88 +90 +A0 +E0 +90 +88 +84 +82 +00 +10 +ENDCHAR +STARTCHAR uni1E33 +ENCODING 7731 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 11 1 -2 +BITMAP +80 +80 +90 +A0 +C0 +C0 +A0 +90 +88 +00 +20 +ENDCHAR +STARTCHAR uni1E34 +ENCODING 7732 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 11 1 -2 +BITMAP +84 +88 +90 +A0 +E0 +90 +88 +84 +82 +00 +78 +ENDCHAR +STARTCHAR uni1E35 +ENCODING 7733 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 11 1 -2 +BITMAP +80 +80 +90 +A0 +C0 +C0 +A0 +90 +88 +00 +F0 +ENDCHAR +STARTCHAR uni1E36 +ENCODING 7734 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 11 1 -2 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +F8 +00 +20 +ENDCHAR +STARTCHAR uni1E37 +ENCODING 7735 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 1 11 1 -2 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +00 +80 +ENDCHAR +STARTCHAR uni1E38 +ENCODING 7736 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 13 0 -2 +BITMAP +F0 +00 +40 +40 +40 +40 +40 +40 +40 +40 +7C +00 +10 +ENDCHAR +STARTCHAR uni1E39 +ENCODING 7737 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 4 13 0 -2 +BITMAP +F0 +00 +40 +40 +40 +40 +40 +40 +40 +40 +40 +00 +40 +ENDCHAR +STARTCHAR uni1E3A +ENCODING 7738 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 11 1 -2 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +F8 +00 +F0 +ENDCHAR +STARTCHAR uni1E3B +ENCODING 7739 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 4 11 0 -2 +BITMAP +40 +40 +40 +40 +40 +40 +40 +40 +40 +00 +F0 +ENDCHAR +STARTCHAR uni1E3C +ENCODING 7740 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 -3 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +F8 +00 +20 +50 +ENDCHAR +STARTCHAR uni1E3D +ENCODING 7741 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 3 12 0 -3 +BITMAP +40 +40 +40 +40 +40 +40 +40 +40 +40 +00 +40 +A0 +ENDCHAR +STARTCHAR uni1E3E +ENCODING 7742 +SWIDTH 833 0 +DWIDTH 11 0 +BBX 9 12 1 0 +BITMAP +0400 +0800 +0000 +8080 +C180 +C180 +A280 +A280 +9480 +9480 +8880 +8880 +ENDCHAR +STARTCHAR uni1E3F +ENCODING 7743 +SWIDTH 833 0 +DWIDTH 9 0 +BBX 7 10 1 0 +BITMAP +08 +10 +00 +A4 +DA +92 +92 +92 +92 +92 +ENDCHAR +STARTCHAR uni1E40 +ENCODING 7744 +SWIDTH 833 0 +DWIDTH 11 0 +BBX 9 11 1 0 +BITMAP +0800 +0000 +8080 +C180 +C180 +A280 +A280 +9480 +9480 +8880 +8880 +ENDCHAR +STARTCHAR uni1E41 +ENCODING 7745 +SWIDTH 833 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +10 +00 +A4 +DA +92 +92 +92 +92 +92 +ENDCHAR +STARTCHAR uni1E42 +ENCODING 7746 +SWIDTH 833 0 +DWIDTH 11 0 +BBX 9 11 1 -2 +BITMAP +8080 +C180 +C180 +A280 +A280 +9480 +9480 +8880 +8880 +0000 +0800 +ENDCHAR +STARTCHAR uni1E43 +ENCODING 7747 +SWIDTH 833 0 +DWIDTH 9 0 +BBX 7 9 1 -2 +BITMAP +A4 +DA +92 +92 +92 +92 +92 +00 +10 +ENDCHAR +STARTCHAR uni1E44 +ENCODING 7748 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +10 +00 +82 +C2 +A2 +A2 +92 +8A +8A +86 +82 +ENDCHAR +STARTCHAR uni1E45 +ENCODING 7749 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 0 +BITMAP +20 +00 +B0 +C8 +88 +88 +88 +88 +88 +ENDCHAR +STARTCHAR uni1E46 +ENCODING 7750 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +82 +C2 +A2 +A2 +92 +8A +8A +86 +82 +00 +10 +ENDCHAR +STARTCHAR uni1E47 +ENCODING 7751 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 -2 +BITMAP +B0 +C8 +88 +88 +88 +88 +88 +00 +20 +ENDCHAR +STARTCHAR uni1E48 +ENCODING 7752 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +82 +C2 +A2 +A2 +92 +8A +8A +86 +82 +00 +3C +ENDCHAR +STARTCHAR uni1E49 +ENCODING 7753 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 -2 +BITMAP +B0 +C8 +88 +88 +88 +88 +88 +00 +78 +ENDCHAR +STARTCHAR uni1E4A +ENCODING 7754 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 12 1 -3 +BITMAP +82 +C2 +A2 +A2 +92 +8A +8A +86 +82 +00 +10 +28 +ENDCHAR +STARTCHAR uni1E4B +ENCODING 7755 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +B0 +C8 +88 +88 +88 +88 +88 +00 +20 +50 +ENDCHAR +STARTCHAR uni1E4C +ENCODING 7756 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 15 1 0 +BITMAP +08 +10 +00 +14 +28 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR uni1E4D +ENCODING 7757 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 13 1 0 +BITMAP +10 +20 +00 +28 +50 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR uni1E4E +ENCODING 7758 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +14 +00 +14 +28 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR uni1E4F +ENCODING 7759 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 0 +BITMAP +50 +00 +28 +50 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR uni1E50 +ENCODING 7760 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +10 +08 +00 +3C +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR uni1E51 +ENCODING 7761 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 0 +BITMAP +40 +20 +00 +78 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR uni1E52 +ENCODING 7762 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 14 1 0 +BITMAP +08 +10 +00 +3C +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR uni1E53 +ENCODING 7763 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 0 +BITMAP +10 +20 +00 +78 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR uni1E54 +ENCODING 7764 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +10 +20 +00 +F8 +84 +84 +84 +F8 +80 +80 +80 +80 +ENDCHAR +STARTCHAR uni1E55 +ENCODING 7765 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 13 1 -3 +BITMAP +10 +20 +00 +B0 +C8 +88 +88 +88 +C8 +B0 +80 +80 +80 +ENDCHAR +STARTCHAR uni1E56 +ENCODING 7766 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +20 +00 +F8 +84 +84 +84 +F8 +80 +80 +80 +80 +ENDCHAR +STARTCHAR uni1E57 +ENCODING 7767 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 -3 +BITMAP +20 +00 +B0 +C8 +88 +88 +88 +C8 +B0 +80 +80 +80 +ENDCHAR +STARTCHAR uni1E58 +ENCODING 7768 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +20 +00 +F8 +84 +84 +84 +F8 +88 +84 +84 +84 +ENDCHAR +STARTCHAR uni1E59 +ENCODING 7769 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 9 1 0 +BITMAP +40 +00 +A0 +C0 +80 +80 +80 +80 +80 +ENDCHAR +STARTCHAR uni1E5A +ENCODING 7770 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 11 1 -2 +BITMAP +F8 +84 +84 +84 +F8 +88 +84 +84 +84 +00 +10 +ENDCHAR +STARTCHAR uni1E5B +ENCODING 7771 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 9 1 -2 +BITMAP +A0 +C0 +80 +80 +80 +80 +80 +00 +80 +ENDCHAR +STARTCHAR uni1E5C +ENCODING 7772 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 13 1 -2 +BITMAP +78 +00 +F8 +84 +84 +84 +F8 +88 +84 +84 +84 +00 +10 +ENDCHAR +STARTCHAR uni1E5D +ENCODING 7773 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 11 0 -2 +BITMAP +F0 +00 +50 +60 +40 +40 +40 +40 +40 +00 +40 +ENDCHAR +STARTCHAR uni1E5E +ENCODING 7774 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 11 1 -2 +BITMAP +F8 +84 +84 +84 +F8 +88 +84 +84 +84 +00 +78 +ENDCHAR +STARTCHAR uni1E5F +ENCODING 7775 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 9 0 -2 +BITMAP +50 +60 +40 +40 +40 +40 +40 +00 +F0 +ENDCHAR +STARTCHAR uni1E60 +ENCODING 7776 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 11 1 0 +BITMAP +20 +00 +78 +84 +80 +60 +18 +04 +84 +84 +78 +ENDCHAR +STARTCHAR uni1E61 +ENCODING 7777 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 9 1 0 +BITMAP +20 +00 +60 +90 +80 +60 +10 +90 +60 +ENDCHAR +STARTCHAR uni1E62 +ENCODING 7778 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 11 1 -2 +BITMAP +78 +84 +80 +60 +18 +04 +84 +84 +78 +00 +10 +ENDCHAR +STARTCHAR uni1E63 +ENCODING 7779 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 9 1 -2 +BITMAP +60 +90 +80 +60 +10 +90 +60 +00 +20 +ENDCHAR +STARTCHAR uni1E64 +ENCODING 7780 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 14 1 0 +BITMAP +10 +00 +10 +20 +00 +78 +84 +80 +60 +18 +04 +84 +84 +78 +ENDCHAR +STARTCHAR uni1E65 +ENCODING 7781 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 12 1 0 +BITMAP +20 +00 +20 +40 +00 +60 +90 +80 +60 +10 +90 +60 +ENDCHAR +STARTCHAR uni1E66 +ENCODING 7782 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 14 1 0 +BITMAP +10 +00 +28 +10 +00 +78 +84 +80 +60 +18 +04 +84 +84 +78 +ENDCHAR +STARTCHAR uni1E67 +ENCODING 7783 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 12 1 0 +BITMAP +40 +00 +A0 +40 +00 +60 +90 +80 +60 +10 +90 +60 +ENDCHAR +STARTCHAR uni1E68 +ENCODING 7784 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 13 1 -2 +BITMAP +20 +00 +78 +84 +80 +60 +18 +04 +84 +84 +78 +00 +10 +ENDCHAR +STARTCHAR uni1E69 +ENCODING 7785 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 11 1 -2 +BITMAP +40 +00 +60 +90 +80 +60 +10 +90 +60 +00 +20 +ENDCHAR +STARTCHAR uni1E6A +ENCODING 7786 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 11 0 0 +BITMAP +10 +00 +FE +10 +10 +10 +10 +10 +10 +10 +10 +ENDCHAR +STARTCHAR uni1E6B +ENCODING 7787 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 11 0 0 +BITMAP +40 +00 +40 +40 +E0 +40 +40 +40 +40 +40 +60 +ENDCHAR +STARTCHAR uni1E6C +ENCODING 7788 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 11 0 -2 +BITMAP +FE +10 +10 +10 +10 +10 +10 +10 +10 +00 +10 +ENDCHAR +STARTCHAR uni1E6D +ENCODING 7789 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 11 0 -2 +BITMAP +40 +40 +E0 +40 +40 +40 +40 +40 +60 +00 +40 +ENDCHAR +STARTCHAR uni1E6E +ENCODING 7790 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 11 0 -2 +BITMAP +FE +10 +10 +10 +10 +10 +10 +10 +10 +00 +3C +ENDCHAR +STARTCHAR uni1E6F +ENCODING 7791 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 4 11 0 -2 +BITMAP +40 +40 +E0 +40 +40 +40 +40 +40 +60 +00 +F0 +ENDCHAR +STARTCHAR uni1E70 +ENCODING 7792 +SWIDTH 611 0 +DWIDTH 7 0 +BBX 7 12 0 -3 +BITMAP +FE +10 +10 +10 +10 +10 +10 +10 +10 +00 +10 +28 +ENDCHAR +STARTCHAR uni1E71 +ENCODING 7793 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 12 0 -3 +BITMAP +40 +40 +E0 +40 +40 +40 +40 +40 +60 +00 +40 +A0 +ENDCHAR +STARTCHAR uni1E72 +ENCODING 7794 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 11 1 -2 +BITMAP +84 +84 +84 +84 +84 +84 +84 +84 +78 +00 +28 +ENDCHAR +STARTCHAR uni1E73 +ENCODING 7795 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 -2 +BITMAP +88 +88 +88 +88 +88 +98 +68 +00 +50 +ENDCHAR +STARTCHAR uni1E74 +ENCODING 7796 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 -3 +BITMAP +84 +84 +84 +84 +84 +84 +84 +84 +78 +00 +28 +50 +ENDCHAR +STARTCHAR uni1E75 +ENCODING 7797 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +88 +88 +88 +88 +88 +98 +68 +00 +50 +A0 +ENDCHAR +STARTCHAR uni1E76 +ENCODING 7798 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 12 1 -3 +BITMAP +84 +84 +84 +84 +84 +84 +84 +84 +78 +00 +10 +28 +ENDCHAR +STARTCHAR uni1E77 +ENCODING 7799 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 -3 +BITMAP +88 +88 +88 +88 +88 +98 +68 +00 +20 +50 +ENDCHAR +STARTCHAR uni1E78 +ENCODING 7800 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 15 1 0 +BITMAP +10 +20 +00 +28 +50 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR uni1E79 +ENCODING 7801 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 13 1 0 +BITMAP +10 +20 +00 +28 +50 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR uni1E7A +ENCODING 7802 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 13 1 0 +BITMAP +28 +00 +78 +00 +84 +84 +84 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR uni1E7B +ENCODING 7803 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 11 1 0 +BITMAP +50 +00 +78 +00 +88 +88 +88 +88 +88 +98 +68 +ENDCHAR +STARTCHAR uni1E7C +ENCODING 7804 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +14 +28 +00 +82 +82 +44 +44 +44 +28 +28 +10 +10 +ENDCHAR +STARTCHAR uni1E7D +ENCODING 7805 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +28 +50 +00 +88 +88 +88 +50 +50 +20 +20 +ENDCHAR +STARTCHAR uni1E7E +ENCODING 7806 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +82 +82 +44 +44 +44 +28 +28 +10 +10 +00 +10 +ENDCHAR +STARTCHAR uni1E7F +ENCODING 7807 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 9 1 -2 +BITMAP +88 +88 +88 +50 +50 +20 +20 +00 +20 +ENDCHAR +STARTCHAR Wgrave +ENCODING 7808 +SWIDTH 944 0 +DWIDTH 11 0 +BBX 9 12 1 0 +BITMAP +1000 +0800 +0000 +8880 +8880 +8880 +4900 +5500 +5500 +2200 +2200 +2200 +ENDCHAR +STARTCHAR wgrave +ENCODING 7809 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 10 0 0 +BITMAP +1000 +0800 +0000 +8880 +8880 +4900 +4900 +5500 +2200 +2200 +ENDCHAR +STARTCHAR Wacute +ENCODING 7810 +SWIDTH 944 0 +DWIDTH 11 0 +BBX 9 12 1 0 +BITMAP +0400 +0800 +0000 +8880 +8880 +8880 +4900 +5500 +5500 +2200 +2200 +2200 +ENDCHAR +STARTCHAR wacute +ENCODING 7811 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 10 0 0 +BITMAP +0400 +0800 +0000 +8880 +8880 +4900 +4900 +5500 +2200 +2200 +ENDCHAR +STARTCHAR Wdieresis +ENCODING 7812 +SWIDTH 944 0 +DWIDTH 11 0 +BBX 9 11 1 0 +BITMAP +1400 +0000 +8880 +8880 +8880 +4900 +5500 +5500 +2200 +2200 +2200 +ENDCHAR +STARTCHAR wdieresis +ENCODING 7813 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 9 0 0 +BITMAP +1400 +0000 +8880 +8880 +4900 +4900 +5500 +2200 +2200 +ENDCHAR +STARTCHAR uni1E86 +ENCODING 7814 +SWIDTH 944 0 +DWIDTH 11 0 +BBX 9 11 1 0 +BITMAP +0800 +0000 +8880 +8880 +8880 +4900 +5500 +5500 +2200 +2200 +2200 +ENDCHAR +STARTCHAR uni1E87 +ENCODING 7815 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 9 0 0 +BITMAP +0800 +0000 +8880 +8880 +4900 +4900 +5500 +2200 +2200 +ENDCHAR +STARTCHAR uni1E88 +ENCODING 7816 +SWIDTH 944 0 +DWIDTH 11 0 +BBX 9 11 1 -2 +BITMAP +8880 +8880 +8880 +4900 +5500 +5500 +2200 +2200 +2200 +0000 +0800 +ENDCHAR +STARTCHAR uni1E89 +ENCODING 7817 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 9 0 -2 +BITMAP +8880 +8880 +4900 +4900 +5500 +2200 +2200 +0000 +0800 +ENDCHAR +STARTCHAR uni1E8A +ENCODING 7818 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +10 +00 +82 +44 +44 +28 +10 +28 +44 +44 +82 +ENDCHAR +STARTCHAR uni1E8B +ENCODING 7819 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +10 +00 +84 +48 +30 +30 +48 +84 +84 +ENDCHAR +STARTCHAR uni1E8C +ENCODING 7820 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +28 +00 +82 +44 +44 +28 +10 +28 +44 +44 +82 +ENDCHAR +STARTCHAR uni1E8D +ENCODING 7821 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 6 9 0 0 +BITMAP +28 +00 +84 +48 +30 +30 +48 +84 +84 +ENDCHAR +STARTCHAR uni1E8E +ENCODING 7822 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 11 1 0 +BITMAP +10 +00 +82 +82 +44 +44 +28 +10 +10 +10 +10 +ENDCHAR +STARTCHAR uni1E8F +ENCODING 7823 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 12 1 -3 +BITMAP +20 +00 +88 +88 +88 +90 +50 +50 +20 +20 +40 +80 +ENDCHAR +STARTCHAR uni1E90 +ENCODING 7824 +SWIDTH 611 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +10 +28 +00 +FE +02 +04 +08 +10 +20 +40 +80 +FE +ENDCHAR +STARTCHAR uni1E91 +ENCODING 7825 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 10 1 0 +BITMAP +20 +50 +00 +F0 +10 +20 +40 +40 +80 +F0 +ENDCHAR +STARTCHAR uni1E92 +ENCODING 7826 +SWIDTH 611 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +FE +02 +04 +08 +10 +20 +40 +80 +FE +00 +10 +ENDCHAR +STARTCHAR uni1E93 +ENCODING 7827 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 9 1 -2 +BITMAP +F0 +10 +20 +40 +40 +80 +F0 +00 +40 +ENDCHAR +STARTCHAR uni1E94 +ENCODING 7828 +SWIDTH 611 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +FE +02 +04 +08 +10 +20 +40 +80 +FE +00 +78 +ENDCHAR +STARTCHAR uni1E95 +ENCODING 7829 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 4 9 1 -2 +BITMAP +F0 +10 +20 +40 +40 +80 +F0 +00 +F0 +ENDCHAR +STARTCHAR uni1E96 +ENCODING 7830 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 11 1 -2 +BITMAP +80 +80 +B0 +C8 +88 +88 +88 +88 +88 +00 +78 +ENDCHAR +STARTCHAR uni1E97 +ENCODING 7831 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 3 11 0 0 +BITMAP +A0 +00 +40 +40 +E0 +40 +40 +40 +40 +40 +60 +ENDCHAR +STARTCHAR uni1E98 +ENCODING 7832 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 9 11 0 0 +BITMAP +0C00 +1200 +0C00 +0000 +8880 +8880 +4900 +4900 +5500 +2200 +2200 +ENDCHAR +STARTCHAR uni1E99 +ENCODING 7833 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 14 1 -3 +BITMAP +30 +48 +30 +00 +88 +88 +88 +90 +50 +50 +20 +20 +40 +80 +ENDCHAR +STARTCHAR uni1EA0 +ENCODING 7840 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +10 +28 +28 +44 +44 +7C +82 +82 +82 +00 +10 +ENDCHAR +STARTCHAR uni1EA1 +ENCODING 7841 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 9 1 -2 +BITMAP +70 +88 +08 +78 +88 +88 +74 +00 +10 +ENDCHAR +STARTCHAR uni1EA4 +ENCODING 7844 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 15 1 0 +BITMAP +08 +10 +00 +10 +28 +00 +10 +10 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR uni1EA5 +ENCODING 7845 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 13 1 0 +BITMAP +10 +20 +00 +20 +50 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR uni1EA6 +ENCODING 7846 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 15 1 0 +BITMAP +20 +10 +00 +10 +28 +00 +10 +10 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR uni1EA7 +ENCODING 7847 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 13 1 0 +BITMAP +40 +20 +00 +20 +50 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR uni1EAA +ENCODING 7850 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 15 1 0 +BITMAP +14 +28 +00 +10 +28 +00 +10 +10 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR uni1EAB +ENCODING 7851 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 13 1 0 +BITMAP +28 +50 +00 +20 +50 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR uni1EAC +ENCODING 7852 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 14 1 -2 +BITMAP +10 +28 +00 +10 +28 +28 +44 +44 +7C +82 +82 +82 +00 +10 +ENDCHAR +STARTCHAR uni1EAD +ENCODING 7853 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 12 1 -2 +BITMAP +20 +50 +00 +70 +88 +08 +78 +88 +88 +74 +00 +10 +ENDCHAR +STARTCHAR uni1EAE +ENCODING 7854 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 15 1 0 +BITMAP +08 +10 +00 +24 +18 +00 +10 +28 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR uni1EAF +ENCODING 7855 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 13 1 0 +BITMAP +10 +20 +00 +48 +30 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR uni1EB0 +ENCODING 7856 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 15 1 0 +BITMAP +20 +10 +00 +24 +18 +00 +10 +28 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR uni1EB1 +ENCODING 7857 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 13 1 0 +BITMAP +20 +10 +00 +48 +30 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR uni1EB4 +ENCODING 7860 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 15 1 0 +BITMAP +14 +28 +00 +24 +18 +00 +10 +28 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR uni1EB5 +ENCODING 7861 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 13 1 0 +BITMAP +28 +50 +00 +48 +30 +00 +70 +88 +08 +78 +88 +88 +74 +ENDCHAR +STARTCHAR uni1EB6 +ENCODING 7862 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 14 1 -2 +BITMAP +24 +18 +00 +10 +28 +28 +44 +44 +7C +82 +82 +82 +00 +10 +ENDCHAR +STARTCHAR uni1EB7 +ENCODING 7863 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 6 12 1 -2 +BITMAP +48 +30 +00 +70 +88 +08 +78 +88 +88 +74 +00 +10 +ENDCHAR +STARTCHAR uni1EB8 +ENCODING 7864 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 11 1 -2 +BITMAP +FC +80 +80 +80 +FC +80 +80 +80 +FC +00 +20 +ENDCHAR +STARTCHAR uni1EB9 +ENCODING 7865 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 -2 +BITMAP +70 +88 +88 +F8 +80 +88 +70 +00 +20 +ENDCHAR +STARTCHAR uni1EBC +ENCODING 7868 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 12 1 0 +BITMAP +28 +50 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR uni1EBD +ENCODING 7869 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 10 1 0 +BITMAP +28 +50 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR uni1EBE +ENCODING 7870 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 15 1 0 +BITMAP +10 +20 +00 +10 +28 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR uni1EBF +ENCODING 7871 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 13 1 0 +BITMAP +10 +20 +00 +20 +50 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR uni1EC0 +ENCODING 7872 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 15 1 0 +BITMAP +20 +10 +00 +10 +28 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR uni1EC1 +ENCODING 7873 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 13 1 0 +BITMAP +40 +20 +00 +20 +50 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR uni1EC4 +ENCODING 7876 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 15 1 0 +BITMAP +28 +50 +00 +10 +28 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +ENDCHAR +STARTCHAR uni1EC5 +ENCODING 7877 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 13 1 0 +BITMAP +28 +50 +00 +20 +50 +00 +70 +88 +88 +F8 +80 +88 +70 +ENDCHAR +STARTCHAR uni1EC6 +ENCODING 7878 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 14 1 -2 +BITMAP +20 +50 +00 +FC +80 +80 +80 +FC +80 +80 +80 +FC +00 +20 +ENDCHAR +STARTCHAR uni1EC7 +ENCODING 7879 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 -2 +BITMAP +20 +50 +00 +70 +88 +88 +F8 +80 +88 +70 +00 +20 +ENDCHAR +STARTCHAR uni1ECA +ENCODING 7882 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 11 1 -2 +BITMAP +80 +80 +80 +80 +80 +80 +80 +80 +80 +00 +80 +ENDCHAR +STARTCHAR uni1ECB +ENCODING 7883 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 1 11 1 -2 +BITMAP +80 +00 +80 +80 +80 +80 +80 +80 +80 +00 +80 +ENDCHAR +STARTCHAR uni1ECC +ENCODING 7884 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 11 1 -2 +BITMAP +3C +42 +81 +81 +81 +81 +81 +42 +3C +00 +08 +ENDCHAR +STARTCHAR uni1ECD +ENCODING 7885 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 -2 +BITMAP +70 +88 +88 +88 +88 +88 +70 +00 +20 +ENDCHAR +STARTCHAR uni1ED0 +ENCODING 7888 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 15 1 0 +BITMAP +08 +10 +00 +08 +14 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR uni1ED1 +ENCODING 7889 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 13 1 0 +BITMAP +10 +20 +00 +20 +50 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR uni1ED2 +ENCODING 7890 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 15 1 0 +BITMAP +10 +08 +00 +08 +14 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR uni1ED3 +ENCODING 7891 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 13 1 0 +BITMAP +40 +20 +00 +20 +50 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR uni1ED6 +ENCODING 7894 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 15 1 0 +BITMAP +14 +28 +00 +08 +14 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +ENDCHAR +STARTCHAR uni1ED7 +ENCODING 7895 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 13 1 0 +BITMAP +28 +50 +00 +20 +50 +00 +70 +88 +88 +88 +88 +88 +70 +ENDCHAR +STARTCHAR uni1ED8 +ENCODING 7896 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 8 14 1 -2 +BITMAP +08 +14 +00 +3C +42 +81 +81 +81 +81 +81 +42 +3C +00 +08 +ENDCHAR +STARTCHAR uni1ED9 +ENCODING 7897 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 -2 +BITMAP +20 +50 +00 +70 +88 +88 +88 +88 +88 +70 +00 +20 +ENDCHAR +STARTCHAR uni1EDA +ENCODING 7898 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 12 1 0 +BITMAP +0200 +0400 +0000 +3CC0 +4240 +8180 +8100 +8100 +8100 +8100 +4200 +3C00 +ENDCHAR +STARTCHAR uni1EDB +ENCODING 7899 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 1 0 +BITMAP +08 +10 +00 +76 +8A +8C +88 +88 +88 +70 +ENDCHAR +STARTCHAR uni1EDC +ENCODING 7900 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 12 1 0 +BITMAP +0800 +0400 +0000 +3CC0 +4240 +8180 +8100 +8100 +8100 +8100 +4200 +3C00 +ENDCHAR +STARTCHAR uni1EDD +ENCODING 7901 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 1 0 +BITMAP +20 +10 +00 +76 +8A +8C +88 +88 +88 +70 +ENDCHAR +STARTCHAR uni1EE0 +ENCODING 7904 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 12 1 0 +BITMAP +0500 +0A00 +0000 +3CC0 +4240 +8180 +8100 +8100 +8100 +8100 +4200 +3C00 +ENDCHAR +STARTCHAR uni1EE1 +ENCODING 7905 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 1 0 +BITMAP +14 +28 +00 +76 +8A +8C +88 +88 +88 +70 +ENDCHAR +STARTCHAR uni1EE2 +ENCODING 7906 +SWIDTH 778 0 +DWIDTH 10 0 +BBX 10 11 1 -2 +BITMAP +3CC0 +4240 +8180 +8100 +8100 +8100 +8100 +4200 +3C00 +0000 +0800 +ENDCHAR +STARTCHAR uni1EE3 +ENCODING 7907 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 -2 +BITMAP +76 +8A +8C +88 +88 +88 +70 +00 +20 +ENDCHAR +STARTCHAR uni1EE4 +ENCODING 7908 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 6 11 1 -2 +BITMAP +84 +84 +84 +84 +84 +84 +84 +84 +78 +00 +10 +ENDCHAR +STARTCHAR uni1EE5 +ENCODING 7909 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 9 1 -2 +BITMAP +88 +88 +88 +88 +88 +98 +68 +00 +20 +ENDCHAR +STARTCHAR uni1EE8 +ENCODING 7912 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 1 0 +BITMAP +04 +08 +00 +87 +85 +86 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR uni1EE9 +ENCODING 7913 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 1 0 +BITMAP +08 +10 +00 +8E +8A +8C +88 +88 +98 +68 +ENDCHAR +STARTCHAR uni1EEA +ENCODING 7914 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 1 0 +BITMAP +10 +08 +00 +87 +85 +86 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR uni1EEB +ENCODING 7915 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 1 0 +BITMAP +10 +08 +00 +8E +8A +8C +88 +88 +98 +68 +ENDCHAR +STARTCHAR uni1EEE +ENCODING 7918 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 12 1 0 +BITMAP +0A +14 +00 +87 +85 +86 +84 +84 +84 +84 +84 +78 +ENDCHAR +STARTCHAR uni1EEF +ENCODING 7919 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 10 1 0 +BITMAP +14 +28 +00 +8E +8A +8C +88 +88 +98 +68 +ENDCHAR +STARTCHAR uni1EF0 +ENCODING 7920 +SWIDTH 722 0 +DWIDTH 8 0 +BBX 8 11 1 -2 +BITMAP +87 +85 +86 +84 +84 +84 +84 +84 +78 +00 +10 +ENDCHAR +STARTCHAR uni1EF1 +ENCODING 7921 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 9 1 -2 +BITMAP +8E +8A +8C +88 +88 +98 +68 +00 +10 +ENDCHAR +STARTCHAR Ygrave +ENCODING 7922 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +20 +10 +00 +82 +82 +44 +44 +28 +10 +10 +10 +10 +ENDCHAR +STARTCHAR ygrave +ENCODING 7923 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 13 1 -3 +BITMAP +40 +20 +00 +88 +88 +88 +90 +50 +50 +20 +20 +40 +80 +ENDCHAR +STARTCHAR uni1EF4 +ENCODING 7924 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 11 1 -2 +BITMAP +82 +82 +44 +44 +28 +10 +10 +10 +10 +00 +10 +ENDCHAR +STARTCHAR uni1EF5 +ENCODING 7925 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 12 1 -5 +BITMAP +88 +88 +88 +90 +50 +50 +20 +20 +40 +80 +00 +40 +ENDCHAR +STARTCHAR uni1EF8 +ENCODING 7928 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +14 +28 +00 +82 +82 +44 +44 +28 +10 +10 +10 +10 +ENDCHAR +STARTCHAR uni1EF9 +ENCODING 7929 +SWIDTH 500 0 +DWIDTH 7 0 +BBX 5 13 1 -3 +BITMAP +28 +50 +00 +88 +88 +88 +90 +50 +50 +20 +20 +40 +80 +ENDCHAR +STARTCHAR uni2000 +ENCODING 8192 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2001 +ENCODING 8193 +SWIDTH 1000 0 +DWIDTH 13 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2002 +ENCODING 8194 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2003 +ENCODING 8195 +SWIDTH 1000 0 +DWIDTH 13 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2004 +ENCODING 8196 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2005 +ENCODING 8197 +SWIDTH 250 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2006 +ENCODING 8198 +SWIDTH 167 0 +DWIDTH 2 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2007 +ENCODING 8199 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2008 +ENCODING 8200 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2009 +ENCODING 8201 +SWIDTH 200 0 +DWIDTH 3 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni200A +ENCODING 8202 +SWIDTH 100 0 +DWIDTH 1 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni200B +ENCODING 8203 +SWIDTH 0 0 +DWIDTH 0 0 +BBX 1 1 0 0 +BITMAP +00 +ENDCHAR +STARTCHAR uni2010 +ENCODING 8208 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 0 3 +BITMAP +F0 +ENDCHAR +STARTCHAR uni2011 +ENCODING 8209 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 4 1 0 3 +BITMAP +F0 +ENDCHAR +STARTCHAR figuredash +ENCODING 8210 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 1 0 3 +BITMAP +FE +ENDCHAR +STARTCHAR endash +ENCODING 8211 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 7 1 0 3 +BITMAP +FE +ENDCHAR +STARTCHAR emdash +ENCODING 8212 +SWIDTH 1000 0 +DWIDTH 12 0 +BBX 12 1 0 3 +BITMAP +FFF0 +ENDCHAR +STARTCHAR afii00208 +ENCODING 8213 +SWIDTH 1000 0 +DWIDTH 12 0 +BBX 12 1 0 3 +BITMAP +FFF0 +ENDCHAR +STARTCHAR quoteleft +ENCODING 8216 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 2 3 0 6 +BITMAP +40 +80 +C0 +ENDCHAR +STARTCHAR quoteright +ENCODING 8217 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 2 3 1 6 +BITMAP +C0 +40 +80 +ENDCHAR +STARTCHAR quotesinglbase +ENCODING 8218 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 2 3 1 -2 +BITMAP +C0 +40 +80 +ENDCHAR +STARTCHAR quotereversed +ENCODING 8219 +SWIDTH 222 0 +DWIDTH 3 0 +BBX 2 3 1 6 +BITMAP +C0 +80 +40 +ENDCHAR +STARTCHAR quotedblleft +ENCODING 8220 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 3 0 6 +BITMAP +48 +90 +D8 +ENDCHAR +STARTCHAR quotedblright +ENCODING 8221 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 3 0 6 +BITMAP +D8 +48 +90 +ENDCHAR +STARTCHAR quotedblbase +ENCODING 8222 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 3 0 -2 +BITMAP +D8 +48 +90 +ENDCHAR +STARTCHAR uni201F +ENCODING 8223 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 5 3 0 6 +BITMAP +D8 +90 +48 +ENDCHAR +STARTCHAR dagger +ENCODING 8224 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 -3 +BITMAP +20 +20 +20 +F8 +20 +20 +20 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR daggerdbl +ENCODING 8225 +SWIDTH 556 0 +DWIDTH 7 0 +BBX 5 12 1 -3 +BITMAP +20 +20 +20 +F8 +20 +20 +20 +20 +F8 +20 +20 +20 +ENDCHAR +STARTCHAR bullet +ENCODING 8226 +SWIDTH 350 0 +DWIDTH 5 0 +BBX 3 3 1 3 +BITMAP +40 +E0 +40 +ENDCHAR +STARTCHAR ellipsis +ENCODING 8230 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 9 1 1 0 +BITMAP +8880 +ENDCHAR +STARTCHAR perthousand +ENCODING 8240 +SWIDTH 1000 0 +DWIDTH 14 0 +BBX 13 8 0 0 +BITMAP +6200 +9400 +9400 +6800 +0B30 +14C8 +14C8 +2330 +ENDCHAR +STARTCHAR guilsinglleft +ENCODING 8249 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 3 5 1 1 +BITMAP +20 +40 +80 +40 +20 +ENDCHAR +STARTCHAR guilsinglright +ENCODING 8250 +SWIDTH 333 0 +DWIDTH 5 0 +BBX 3 5 1 1 +BITMAP +80 +40 +20 +40 +80 +ENDCHAR +STARTCHAR fraction +ENCODING 8260 +SWIDTH 167 0 +DWIDTH 4 0 +BBX 5 8 -1 0 +BITMAP +08 +10 +10 +20 +20 +40 +40 +80 +ENDCHAR +STARTCHAR oneinferior +ENCODING 8321 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 2 5 1 -3 +BITMAP +40 +C0 +40 +40 +40 +ENDCHAR +STARTCHAR twoinferior +ENCODING 8322 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 4 5 0 -3 +BITMAP +60 +90 +20 +40 +F0 +ENDCHAR +STARTCHAR threeinferior +ENCODING 8323 +SWIDTH 333 0 +DWIDTH 4 0 +BBX 3 5 0 -3 +BITMAP +E0 +20 +40 +20 +C0 +ENDCHAR +STARTCHAR uni20A5 +ENCODING 8357 +SWIDTH 833 0 +DWIDTH 9 0 +BBX 7 9 1 -1 +BITMAP +04 +A4 +DA +9A +92 +92 +92 +B2 +20 +ENDCHAR +STARTCHAR uni20A6 +ENCODING 8358 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +82 +C2 +A2 +FE +92 +FE +8A +86 +82 +ENDCHAR +STARTCHAR uni20A9 +ENCODING 8361 +SWIDTH 944 0 +DWIDTH 11 0 +BBX 9 9 1 0 +BITMAP +8880 +8880 +8880 +7F00 +5500 +7F00 +2200 +2200 +2200 +ENDCHAR +STARTCHAR Euro +ENCODING 8364 +SWIDTH 722 0 +DWIDTH 9 0 +BBX 8 9 0 0 +BITMAP +1E +21 +40 +F8 +40 +F8 +40 +21 +1E +ENDCHAR +STARTCHAR uni20AD +ENCODING 8365 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 9 1 0 +BITMAP +84 +88 +90 +A0 +FE +90 +88 +84 +82 +ENDCHAR +STARTCHAR uni2103 +ENCODING 8451 +SWIDTH 1102 0 +DWIDTH 14 0 +BBX 13 9 0 0 +BITMAP +00F0 +6108 +9200 +9200 +6200 +0200 +0200 +0108 +00F0 +ENDCHAR +STARTCHAR uni2109 +ENCODING 8457 +SWIDTH 991 0 +DWIDTH 13 0 +BBX 12 9 0 0 +BITMAP +03F0 +6200 +9200 +9200 +63E0 +0200 +0200 +0200 +0200 +ENDCHAR +STARTCHAR trademark +ENCODING 8482 +SWIDTH 1000 0 +DWIDTH 11 0 +BBX 9 5 1 4 +BITMAP +E880 +4D80 +4D80 +4A80 +4A80 +ENDCHAR +STARTCHAR uni212A +ENCODING 8490 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 7 9 1 0 +BITMAP +84 +88 +90 +A0 +E0 +90 +88 +84 +82 +ENDCHAR +STARTCHAR uni212B +ENCODING 8491 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 12 1 0 +BITMAP +10 +28 +10 +10 +10 +28 +44 +44 +7C +82 +82 +82 +ENDCHAR +STARTCHAR uni2132 +ENCODING 8498 +SWIDTH 611 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +04 +04 +04 +04 +7C +04 +04 +04 +FC +ENDCHAR +STARTCHAR universal +ENCODING 8704 +SWIDTH 667 0 +DWIDTH 9 0 +BBX 7 9 1 0 +BITMAP +82 +82 +82 +7C +44 +44 +28 +28 +10 +ENDCHAR +STARTCHAR existential +ENCODING 8707 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +FC +04 +04 +04 +FC +04 +04 +04 +FC +ENDCHAR +STARTCHAR uni2204 +ENCODING 8708 +SWIDTH 667 0 +DWIDTH 8 0 +BBX 6 9 1 0 +BITMAP +FC +0C +14 +14 +FC +24 +24 +44 +FC +ENDCHAR +STARTCHAR minus +ENCODING 8722 +SWIDTH 584 0 +DWIDTH 8 0 +BBX 5 1 1 3 +BITMAP +F8 +ENDCHAR +STARTCHAR fraction +ENCODING 8725 +SWIDTH 167 0 +DWIDTH 4 0 +BBX 5 8 -1 0 +BITMAP +08 +10 +10 +20 +20 +40 +40 +80 +ENDCHAR +STARTCHAR periodcentered +ENCODING 8729 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 1 1 3 +BITMAP +80 +ENDCHAR +STARTCHAR uni2236 +ENCODING 8758 +SWIDTH 278 0 +DWIDTH 3 0 +BBX 1 6 1 0 +BITMAP +80 +00 +00 +00 +00 +80 +ENDCHAR +STARTCHAR uni2259 +ENCODING 8793 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 6 1 2 +BITMAP +20 +50 +00 +F8 +00 +F8 +ENDCHAR +STARTCHAR uni225A +ENCODING 8794 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 6 1 2 +BITMAP +50 +20 +00 +F8 +00 +F8 +ENDCHAR +STARTCHAR notequal +ENCODING 8800 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 9 1 -1 +BITMAP +08 +08 +10 +F8 +20 +F8 +20 +40 +40 +ENDCHAR +STARTCHAR equivalence +ENCODING 8801 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 5 0 1 +BITMAP +F8 +00 +F8 +00 +F8 +ENDCHAR +STARTCHAR uni2262 +ENCODING 8802 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 5 9 0 -1 +BITMAP +08 +08 +F8 +10 +F8 +20 +F8 +40 +40 +ENDCHAR +STARTCHAR lessequal +ENCODING 8804 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 7 0 -1 +BITMAP +0C +30 +C0 +30 +0C +00 +FC +ENDCHAR +STARTCHAR greaterequal +ENCODING 8805 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 7 1 -1 +BITMAP +C0 +30 +0C +30 +C0 +00 +FC +ENDCHAR +STARTCHAR uni226E +ENCODING 8814 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 9 0 -1 +BITMAP +08 +08 +1C +30 +E0 +30 +2C +40 +40 +ENDCHAR +STARTCHAR uni226F +ENCODING 8815 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 9 1 -1 +BITMAP +08 +08 +D0 +30 +2C +30 +E0 +40 +40 +ENDCHAR +STARTCHAR uni2270 +ENCODING 8816 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 9 0 -2 +BITMAP +08 +0C +30 +D0 +30 +2C +20 +FC +40 +ENDCHAR +STARTCHAR uni2271 +ENCODING 8817 +SWIDTH 584 0 +DWIDTH 7 0 +BBX 6 9 1 -2 +BITMAP +08 +C8 +30 +1C +30 +E0 +20 +FC +40 +ENDCHAR +STARTCHAR fi +ENCODING -1 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +38 +40 +E8 +48 +48 +48 +48 +48 +48 +ENDCHAR +STARTCHAR fl +ENCODING -1 +SWIDTH 500 0 +DWIDTH 6 0 +BBX 5 9 0 0 +BITMAP +38 +48 +E8 +48 +48 +48 +48 +48 +48 +ENDCHAR +ENDFONT diff --git a/gui/themes/fonts/topaz/README.ScummVM b/gui/themes/fonts/topaz/README.ScummVM new file mode 100644 index 0000000000..3beea8a048 --- /dev/null +++ b/gui/themes/fonts/topaz/README.ScummVM @@ -0,0 +1,6 @@ +This package is a remake of Amiga built-in Topaz font for use with Lithuanian keyboards. +You will find detailed information in topazLT.readme. + +The Parallaction engine in ScummVM uses this font's bitmap, namely file topazlt/8. +Data has been extracted and placed in the array named _amigaTopazFont which can be found in engines/parallaction/staticres.cpp. + diff --git a/gui/themes/fonts/topaz/topazLT.font b/gui/themes/fonts/topaz/topazLT.font Binary files differnew file mode 100644 index 0000000000..e60de8600d --- /dev/null +++ b/gui/themes/fonts/topaz/topazLT.font diff --git a/gui/themes/fonts/topaz/topazLT.readme b/gui/themes/fonts/topaz/topazLT.readme new file mode 100644 index 0000000000..3c3553d6ec --- /dev/null +++ b/gui/themes/fonts/topaz/topazLT.readme @@ -0,0 +1,63 @@ +Short: Topaz with Lithuanian characters +Uploader: r.ulozas@kaunas.omnitel.net (Ricardas Ulozas) +Author: r.ulozas@kaunas.omnitel.net (Ricardas Ulozas) +Type: text/font +Version: 1.0 + +WHAT IS IT? +This font has BalticRim layout standard for Lithuanian, Latvian, +Estonian, Finnish, Polish, Czech and other Central European +countries. It is very useful when browsing through different +Lithuanian or Latvian Web sites as you may see the special +diacritic signs, or when typing in the aforementioned languages. + +WHAT DO YOU NEED? +To type in Lithuanian, please download BalticRimLT.lha on +Aminet. + +HOW TO RUN IT? +First, extract: lha x topazLT.lha fonts: +Second, select it on your famous text editor or DTP program. + +WHOM I WANT TO THANK? +Commodore-Amiga,Inc. - Steve Beats and Andy Finkel for FED +CygnusSoft for CED +Phase5 for PPC card (when will I get it?...) +Duckman, Smartie, Beavis and others for being so smart. + +HOW YOU MAY DISTRIBUTE IT? +Anyone, anywhere, anytime, anyway, anywise, etc. as long as you +don't make money on it (if you do, write me, I'd like to know +how ;) ) + +WHAT IF YOU WANT TO KEEP IT? +If you liked it I ask you to send me a postcard with your city +sights. Those lazy-bones, tramps and other poor creatures may +write me an e-mail. + +WHAT IF YOU WANT TO CONTACT ME? +OK, for bug reports, excited or disappointed letters, requests +for other versions (Hmm..), ideas please write to: + + r.ulozas@kaunas.omnitel.net + +If you are a female, have sexy voice and want to have a good +chat with a guy thousand miles away, make a call: + + 370-7-223859 + +And if you want to send me a postcard, money, a PPC board, a +monitor or a stone brick, better try the slow medieval way: + + Ricardas Ulozas + POB 2133 + LT-3000 Kaunas + Lithuania + +WHAT IS IN THE FUTURE? +Some new characters to make it fully BalticRim-compatible. +Sizes 9 and 11 - fixed width. +Vector font - huge MAYBE. +Improved documentation. + +That's it. Enjoy the font and support Amiga! diff --git a/gui/themes/fonts/topaz/topazlt/8 b/gui/themes/fonts/topaz/topazlt/8 Binary files differnew file mode 100644 index 0000000000..e74eeb94ef --- /dev/null +++ b/gui/themes/fonts/topaz/topazlt/8 diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip Binary files differindex 67cbbf7990..b5866337ad 100644 --- a/gui/themes/scummclassic.zip +++ b/gui/themes/scummclassic.zip diff --git a/gui/themes/scummclassic/classic_gfx.stx b/gui/themes/scummclassic/classic_gfx.stx index cc6d7d471f..8c03aa932c 100644 --- a/gui/themes/scummclassic/classic_gfx.stx +++ b/gui/themes/scummclassic/classic_gfx.stx @@ -44,13 +44,28 @@ <fonts> <font id = 'text_default' - file = 'default' + file = 'helvb12.bdf' + /> + <font resolution = '320xY, 256x240' + id = 'text_default' + file = 'clR6x12.bdf' /> <font id = 'text_button' - file = 'default' + file = 'helvb12.bdf' + /> + <font resolution = '320xY, 256x240' + id = 'text_button' + file = 'clR6x12.bdf' /> <font id = 'text_normal' - file = 'default' + file = 'helvb12.bdf' + /> + <font resolution = '320xY, 256x240' + id = 'text_normal' + file = 'clR6x12.bdf' + /> + <font id = 'tooltip_normal' + file = 'fixed5x8.bdf' /> <text_color id = 'color_normal' @@ -418,9 +433,78 @@ /> </drawdata> + <!-- Idle radiobutton --> + <drawdata id = 'radiobutton_default' cache = 'false'> + <text font = 'text_default' + text_color = 'color_normal' + vertical_align = 'center' + horizontal_align = 'left' + /> + <drawstep func = 'circle' + width = '7' + height = '7' + radius = '7' + fill = 'background' + bg_color = 'darkgrey' + xpos = '0' + ypos = '0' + /> + </drawdata> + + <!-- Selected radiobutton --> + <drawdata id = 'radiobutton_selected' cache = 'false'> + <text font = 'text_default' + text_color = 'color_normal' + vertical_align = 'center' + horizontal_align = 'left' + /> + <drawstep func = 'circle' + width = '7' + height = '7' + radius = '7' + fg_color = 'darkgrey' + fill = 'none' + xpos = '0' + ypos = '0' + /> + <drawstep func = 'circle' + width = '7' + height = '7' + radius = '5' + fg_color = 'green' + fill = 'foreground' + xpos = '2' + ypos = '2' + /> + </drawdata> + + <!-- Disabled radiobutton --> + <drawdata id = 'radiobutton_disabled' cache = 'false'> + <text font = 'text_default' + text_color = 'color_normal_disabled' + vertical_align = 'center' + horizontal_align = 'left' + /> + <drawstep func = 'circle' + width = '7' + height = '7' + radius = '7' + bg_color = 'lightgrey' + fill = 'background' + xpos = '0' + ypos = '0' + /> + </drawdata> + <drawdata id = 'widget_default' cache = 'false'> <drawstep func = 'bevelsq' bevel = '2' /> </drawdata> + + <drawdata id = 'widget_small' cache = 'false'> + <drawstep func = 'square' + stroke = '0' + /> + </drawdata> </render_info> diff --git a/gui/themes/scummclassic/classic_layout.stx b/gui/themes/scummclassic/classic_layout.stx index 14f19a7151..80bc4bf41e 100644 --- a/gui/themes/scummclassic/classic_layout.stx +++ b/gui/themes/scummclassic/classic_layout.stx @@ -41,6 +41,10 @@ <def var = 'KeyMapper.LabelWidth' value = '100'/> <def var = 'KeyMapper.ButtonWidth' value = '80'/> + <def var = 'Tooltip.MaxWidth' value = '200'/> + <def var = 'Tooltip.XDelta' value = '16'/> <!-- basically cursor size --> + <def var = 'Tooltip.YDelta' value = '16'/> + <widget name = 'OptionsLabel' size = '110, Globals.Line.Height' textalign = 'right' @@ -66,6 +70,9 @@ <widget name = 'Checkbox' size = '-1, 14' /> + <widget name = 'Radiobutton' + size = '-1, Globals.Line.Height' + /> <widget name = 'ListWidget' padding = '5, 0, 8, 0' /> @@ -85,6 +92,9 @@ size = '75, 27' padding = '0, 0, 8, 0' /> + <widget name = 'TabWidget.Body' + padding = '0, 0, 0, 0' + /> <widget name = 'TabWidget.NavButton' size = '15, 18' padding = '0, 3, 4, 0' @@ -222,6 +232,22 @@ /> </layout> <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'auPrefMt32PopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auPrefMt32Popup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'auPrefGmPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auPrefGmPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> <widget name = 'auOPLPopupDesc' type = 'OptionsLabel' /> @@ -241,9 +267,14 @@ <widget name = 'subToggleDesc' type = 'OptionsLabel' /> - <widget name = 'subToggleButton' - width = '150' - height = 'Globals.Slider.Height' + <widget name = 'subToggleSpeechOnly' + type = 'Radiobutton' + /> + <widget name = 'subToggleSubOnly' + type = 'Radiobutton' + /> + <widget name = 'subToggleSubBoth' + type = 'Radiobutton' /> </layout> <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> @@ -406,6 +437,14 @@ type = 'PopUp' /> </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'GuiLanguagePopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'GuiLanguagePopup' + type = 'PopUp' + /> + </layout> <widget name='KeysButton' type='Button' /> @@ -653,9 +692,17 @@ <widget name = 'subToggleDesc' type = 'OptionsLabel' /> - <widget name = 'subToggleButton' - width = '158' - height = 'Globals.Slider.Height' + <widget name = 'subToggleSpeechOnly' + type = 'Radiobutton' + width = '100' + /> + <widget name = 'subToggleSubOnly' + type = 'Radiobutton' + width = '100' + /> + <widget name = 'subToggleSubBoth' + type = 'Radiobutton' + width = '100' /> </layout> <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> diff --git a/gui/themes/scummclassic/classic_layout_lowres.stx b/gui/themes/scummclassic/classic_layout_lowres.stx index 8a0180db3c..64ac6e200a 100644 --- a/gui/themes/scummclassic/classic_layout_lowres.stx +++ b/gui/themes/scummclassic/classic_layout_lowres.stx @@ -42,6 +42,10 @@ <def var = 'KeyMapper.LabelWidth' value = '80'/> <def var = 'KeyMapper.ButtonWidth' value = '60'/> + <def var = 'Tooltip.MaxWidth' value = '70'/> + <def var = 'Tooltip.XDelta' value = '8'/> <!-- basically cursor size --> + <def var = 'Tooltip.YDelta' value = '8'/> + <widget name = 'Button' size = '72, 16' /> @@ -63,6 +67,9 @@ <widget name = 'Checkbox' size = '-1, Globals.Line.Height' /> + <widget name = 'Radiobutton' + size = '-1, Globals.Line.Height' + /> <widget name = 'ListWidget' padding = '5, 0, 0, 0' /> @@ -82,6 +89,9 @@ size = '45, 16' padding = '0, 0, 2, 0' /> + <widget name = 'TabWidget.Body' + padding = '0, 0, 0, 0' + /> <widget name = 'TabWidget.NavButton' size = '32, 18' padding = '0, 3, 4, 0' @@ -89,11 +99,11 @@ </globals> <dialog name = 'Launcher' overlays = 'screen'> - <layout type = 'vertical' center = 'true' padding = '8, 8, 4, 4'> + <layout type = 'vertical' center = 'true' padding = '6, 6, 2, 2'> <widget name = 'Version' height = 'Globals.Line.Height' /> - <layout type = 'horizontal' spacing = '5' padding = '10, 0, 0, 0'> + <layout type = 'horizontal' spacing = '5' padding = '0, 0, 0, 0'> <widget name = 'SearchDesc' width = '50' height = 'Globals.Line.Height' @@ -110,7 +120,7 @@ <space /> </layout> <widget name = 'GameList'/> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> <widget name = 'LoadGameButton' height = '12' /> @@ -124,7 +134,7 @@ height = '12' /> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '8'> <widget name = 'QuitButton' height = '12' /> @@ -220,6 +230,22 @@ /> </layout> <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'auPrefMt32PopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auPrefMt32Popup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'auPrefGmPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auPrefGmPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> <widget name = 'auOPLPopupDesc' type = 'OptionsLabel' /> @@ -235,13 +261,18 @@ type = 'PopUp' /> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '3' center = 'true'> <widget name = 'subToggleDesc' type = 'OptionsLabel' /> - <widget name = 'subToggleButton' - width = '128' - height = 'Globals.Slider.Height' + <widget name = 'subToggleSpeechOnly' + type = 'Radiobutton' + /> + <widget name = 'subToggleSubOnly' + type = 'Radiobutton' + /> + <widget name = 'subToggleSubBoth' + type = 'Radiobutton' /> </layout> <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> @@ -407,6 +438,16 @@ type = 'PopUp' /> </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'GuiLanguagePopupDesc' + width = '80' + height = 'Globals.Line.Height' + textalign = 'right' + /> + <widget name = 'GuiLanguagePopup' + type = 'PopUp' + /> + </layout> <widget name='KeysButton' type='Button' /> @@ -655,15 +696,26 @@ /> </layout> <space size = '4' /> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <layout type = 'vertical' padding = '0, 0, 0, 0' spacing = '1' center = 'true'> <widget name = 'subToggleDesc' type = 'OptionsLabel' /> - <widget name = 'subToggleButton' - width = '128' - height = 'Globals.Slider.Height' - /> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'subToggleSpeechOnly' + type = 'Radiobutton' + width = '90' + /> + <widget name = 'subToggleSubOnly' + type = 'Radiobutton' + width = '90' + /> + <widget name = 'subToggleSubBoth' + type = 'Radiobutton' + width = '90' + /> + </layout> </layout> + <space size = '4' /> <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> <widget name = 'subSubtitleSpeedDesc' type = 'OptionsLabel' diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip Binary files differindex b3dc16b67e..aba0c944c3 100644 --- a/gui/themes/scummmodern.zip +++ b/gui/themes/scummmodern.zip diff --git a/gui/themes/scummmodern/radiobutton.bmp b/gui/themes/scummmodern/radiobutton.bmp Binary files differnew file mode 100644 index 0000000000..d3ba468321 --- /dev/null +++ b/gui/themes/scummmodern/radiobutton.bmp diff --git a/gui/themes/scummmodern/radiobutton_empty.bmp b/gui/themes/scummmodern/radiobutton_empty.bmp Binary files differnew file mode 100644 index 0000000000..06b9f9bb70 --- /dev/null +++ b/gui/themes/scummmodern/radiobutton_empty.bmp diff --git a/gui/themes/scummmodern/scummmodern_gfx.stx b/gui/themes/scummmodern/scummmodern_gfx.stx index 05316b516f..ad41475a96 100644 --- a/gui/themes/scummmodern/scummmodern_gfx.stx +++ b/gui/themes/scummmodern/scummmodern_gfx.stx @@ -98,19 +98,36 @@ <bitmap filename = 'cursor_small.bmp'/> <bitmap filename = 'checkbox.bmp'/> <bitmap filename = 'checkbox_empty.bmp'/> + <bitmap filename = 'radiobutton.bmp'/> + <bitmap filename = 'radiobutton_empty.bmp'/> <bitmap filename = 'logo_small.bmp'/> <bitmap filename = 'search.bmp'/> </bitmaps> <fonts> <font id = 'text_default' - file = 'default' + file = 'helvb12.bdf' + /> + <font resolution = '320xY, 256x240' + id = 'text_default' + file = 'clR6x12.bdf' /> <font id = 'text_button' - file = 'default' + file = 'helvb12.bdf' + /> + <font resolution = '320xY, 256x240' + id = 'text_button' + file = 'clR6x12.bdf' /> <font id = 'text_normal' - file = 'helvr12-l1.bdf' + file = 'helvb12.bdf' + /> + <font resolution = '320xY, 256x240' + id = 'text_normal' + file = 'clR6x12.bdf' + /> + <font id = 'tooltip_normal' + file = 'fixed5x8.bdf' /> <text_color id = 'color_normal' @@ -595,6 +612,42 @@ /> </drawdata> + <!-- Idle radiobutton --> + <drawdata id = 'radiobutton_default' cache = 'false'> + <text font = 'text_default' + text_color = 'color_normal' + vertical_align = 'center' + horizontal_align = 'left' + /> + <drawstep func = 'bitmap' + file = 'radiobutton_empty.bmp' + /> + </drawdata> + + <!-- Selected radiobutton --> + <drawdata id = 'radiobutton_selected' cache = 'false'> + <text font = 'text_default' + text_color = 'color_normal' + vertical_align = 'center' + horizontal_align = 'left' + /> + <drawstep func = 'bitmap' + file = 'radiobutton.bmp' + /> + </drawdata> + + <!-- Disabled radiobutton --> + <drawdata id = 'radiobutton_disabled' cache = 'false'> + <text font = 'text_default' + text_color = 'color_normal_disabled' + vertical_align = 'center' + horizontal_align = 'left' + /> + <drawstep func = 'bitmap' + file = 'radiobutton_empty.bmp' + /> + </drawdata> + <!-- Background of the list widget (the games list and the list in the choosers) --> <!-- TODO: Have separate options for the games list (with gradient background) and the list in the choosers (without gradient) --> <drawdata id = 'widget_default' cache = 'false'> @@ -611,10 +664,8 @@ /> </drawdata> - <!-- Where is it used? --> <drawdata id = 'widget_small' cache = 'false'> - <drawstep func = 'roundedsq' - radius = '6' + <drawstep func = 'square' stroke = '0' gradient_start = 'blandyellow' gradient_end = 'xtrabrightred' diff --git a/gui/themes/scummmodern/scummmodern_layout.stx b/gui/themes/scummmodern/scummmodern_layout.stx index 25add37462..796d4d9a94 100644 --- a/gui/themes/scummmodern/scummmodern_layout.stx +++ b/gui/themes/scummmodern/scummmodern_layout.stx @@ -48,6 +48,10 @@ <def var = 'KeyMapper.LabelWidth' value = '100'/> <def var = 'KeyMapper.ButtonWidth' value = '80'/> + <def var = 'Tooltip.MaxWidth' value = '200'/> + <def var = 'Tooltip.XDelta' value = '16'/> <!-- basically cursor size --> + <def var = 'Tooltip.YDelta' value = '32'/> + <widget name = 'OptionsLabel' size = '110, Globals.Line.Height' textalign = 'right' @@ -70,6 +74,9 @@ <widget name = 'Checkbox' size = '-1, Globals.Line.Height' /> + <widget name = 'Radiobutton' + size = '-1, Globals.Line.Height' + /> <widget name = 'ListWidget' padding = '5, 0, 8, 0' /> @@ -89,6 +96,11 @@ size = '75, 27' padding = '0, 0, 8, 0' /> + + <widget name = 'TabWidget.Body' + padding = '0, 0, 0, 0' + /> + <widget name = 'TabWidget.NavButton' size = '15, 18' padding = '0, 3, 4, 0' @@ -98,7 +110,7 @@ <dialog name = 'Launcher' overlays = 'screen'> <layout type = 'vertical' center = 'true' padding = '23, 23, 8, 23'> <widget name = 'Logo' - width = '283' + width = '287' height = '80' /> <layout type = 'horizontal' spacing = '5' padding = '10, 0, 0, 0'> @@ -235,6 +247,22 @@ /> </layout> <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'auPrefMt32PopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auPrefMt32Popup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'auPrefGmPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auPrefGmPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> <widget name = 'auOPLPopupDesc' type = 'OptionsLabel' /> @@ -254,9 +282,14 @@ <widget name = 'subToggleDesc' type = 'OptionsLabel' /> - <widget name = 'subToggleButton' - width = '150' - height = 'Globals.Slider.Height' + <widget name = 'subToggleSpeechOnly' + type = 'Radiobutton' + /> + <widget name = 'subToggleSubOnly' + type = 'Radiobutton' + /> + <widget name = 'subToggleSubBoth' + type = 'Radiobutton' /> </layout> <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> @@ -419,6 +452,14 @@ type = 'PopUp' /> </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'> + <widget name = 'GuiLanguagePopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'GuiLanguagePopup' + type = 'PopUp' + /> + </layout> <widget name='KeysButton' type='Button' /> @@ -666,9 +707,17 @@ <widget name = 'subToggleDesc' type = 'OptionsLabel' /> - <widget name = 'subToggleButton' - width = '158' - height = 'Globals.Slider.Height' + <widget name = 'subToggleSpeechOnly' + type = 'Radiobutton' + width = '100' + /> + <widget name = 'subToggleSubOnly' + type = 'Radiobutton' + width = '100' + /> + <widget name = 'subToggleSubBoth' + type = 'Radiobutton' + width = '100' /> </layout> <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10'> diff --git a/gui/themes/scummmodern/scummmodern_layout_lowres.stx b/gui/themes/scummmodern/scummmodern_layout_lowres.stx index 1c2f83a3b7..8bb31e9f8a 100644 --- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx +++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx @@ -48,6 +48,10 @@ <def var = 'KeyMapper.LabelWidth' value = '80'/> <def var = 'KeyMapper.ButtonWidth' value = '60'/> + <def var = 'Tooltip.MaxWidth' value = '70'/> + <def var = 'Tooltip.XDelta' value = '9'/> <!-- basically cursor size --> + <def var = 'Tooltip.YDelta' value = '18'/> + <widget name = 'OptionsLabel' size = '100, Globals.Line.Height' textalign = 'right' @@ -61,6 +65,9 @@ <widget name = 'Checkbox' size = '-1, Globals.Line.Height' /> + <widget name = 'Radiobutton' + size = '-1, Globals.Line.Height' + /> <widget name = 'ListWidget' padding = '5, 0, 8, 0' /> @@ -80,6 +87,9 @@ size = '45, 16' padding = '0, 0, 2, 0' /> + <widget name = 'TabWidget.Body' + padding = '0, 0, 0, 0' + /> <widget name = 'TabWidget.NavButton' size = '32, 18' padding = '0, 3, 4, 0' @@ -87,11 +97,11 @@ </globals> <dialog name = 'Launcher' overlays = 'screen'> - <layout type = 'vertical' center = 'true' padding = '8, 8, 8, 4' spacing = '8'> + <layout type = 'vertical' center = 'true' padding = '4, 4, 2, 2' spacing = '2'> <widget name = 'Version' height = 'Globals.Line.Height' /> - <layout type = 'horizontal' spacing = '5' padding = '10, 0, 0, 0'> + <layout type = 'horizontal' spacing = '5' padding = '0, 0, 2, 2'> <widget name = 'SearchDesc' width = '50' height = 'Globals.Line.Height' @@ -108,7 +118,7 @@ <space /> </layout> <widget name = 'GameList'/> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6'> + <layout type = 'horizontal' padding = '0, 0, 2, 0' spacing = '2'> <widget name = 'LoadGameButton' height = 'Globals.Button.Height' /> @@ -122,7 +132,7 @@ height = 'Globals.Button.Height' /> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '2'> <widget name = 'QuitButton' height = 'Globals.Button.Height' /> @@ -218,6 +228,22 @@ /> </layout> <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'auPrefMt32PopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auPrefMt32Popup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'auPrefGmPopupDesc' + type = 'OptionsLabel' + /> + <widget name = 'auPrefGmPopup' + type = 'PopUp' + /> + </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> <widget name = 'auOPLPopupDesc' type = 'OptionsLabel' /> @@ -233,13 +259,18 @@ type = 'PopUp' /> </layout> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '3' center = 'true'> <widget name = 'subToggleDesc' type = 'OptionsLabel' /> - <widget name = 'subToggleButton' - width = '128' - height = 'Globals.Slider.Height' + <widget name = 'subToggleSpeechOnly' + type = 'Radiobutton' + /> + <widget name = 'subToggleSubOnly' + type = 'Radiobutton' + /> + <widget name = 'subToggleSubBoth' + type = 'Radiobutton' /> </layout> <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> @@ -389,6 +420,7 @@ <widget name = 'RendererPopupDesc' width = '80' height = 'Globals.Line.Height' + textalign = 'right' /> <widget name = 'RendererPopup' type = 'PopUp' @@ -398,11 +430,22 @@ <widget name = 'AutosavePeriodPopupDesc' width = '80' height = 'Globals.Line.Height' + textalign = 'right' /> <widget name = 'AutosavePeriodPopup' type = 'PopUp' /> </layout> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'GuiLanguagePopupDesc' + width = '80' + height = 'Globals.Line.Height' + textalign = 'right' + /> + <widget name = 'GuiLanguagePopup' + type = 'PopUp' + /> + </layout> <widget name='KeysButton' type='Button' /> @@ -651,15 +694,26 @@ /> </layout> <space size = '4' /> - <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <layout type = 'vertical' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> <widget name = 'subToggleDesc' type = 'OptionsLabel' /> - <widget name = 'subToggleButton' - width = '128' - height = 'Globals.Slider.Height' - /> + <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> + <widget name = 'subToggleSpeechOnly' + type = 'Radiobutton' + width = '90' + /> + <widget name = 'subToggleSubOnly' + type = 'Radiobutton' + width = '90' + /> + <widget name = 'subToggleSubBoth' + type = 'Radiobutton' + width = '90' + /> + </layout> </layout> + <space size = '4' /> <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'> <widget name = 'subSubtitleSpeedDesc' type = 'OptionsLabel' diff --git a/gui/widget.cpp b/gui/widget.cpp index e4b37dc3c2..14cb61006b 100644 --- a/gui/widget.cpp +++ b/gui/widget.cpp @@ -32,14 +32,14 @@ namespace GUI { -Widget::Widget(GuiObject *boss, int x, int y, int w, int h) - : GuiObject(x, y, w, h), _type(0), _boss(boss), +Widget::Widget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip) + : GuiObject(x, y, w, h), _type(0), _boss(boss), _tooltip(tooltip), _id(0), _flags(0), _hasFocus(false), _state(ThemeEngine::kStateEnabled) { init(); } -Widget::Widget(GuiObject *boss, const Common::String &name) - : GuiObject(name), _type(0), _boss(boss), +Widget::Widget(GuiObject *boss, const Common::String &name, const char *tooltip) + : GuiObject(name), _type(0), _boss(boss), _tooltip(tooltip), _id(0), _flags(0), _hasFocus(false), _state(ThemeEngine::kStateDisabled) { init(); } @@ -177,17 +177,139 @@ bool Widget::isVisible() const { return !(_flags & WIDGET_INVISIBLE); } +uint8 Widget::parseHotkey(const Common::String &label) { + if (!label.contains('~')) + return 0; + + int state = 0; + uint8 hotkey = 0; + + for (uint i = 0; i < label.size() && state != 3; i++) { + switch (state) { + case 0: + if (label[i] == '~') + state = 1; + break; + case 1: + if (label[i] != '~') { + state = 2; + hotkey = label[i]; + } else + state = 0; + break; + case 2: + if (label[i] == '~') + state = 3; + else + state = 0; + break; + } + } + + if (state == 3) + return hotkey; + + return 0; +} + +Common::String Widget::cleanupHotkey(const Common::String &label) { + Common::String res; + + for (uint i = 0; i < label.size() ; i++) + if (label[i] != '~') + res = res + label[i]; + + return res; +} + +#pragma mark - + +Tooltip::Tooltip(GuiManager *guiManager) : GuiObject(0, 0, 0, 0) { + _guiManager = guiManager; + + _visible = false; + _maxWidth = -1; + _storedState = 0; +} + +void Tooltip::draw() { + int num = 0; + int h = g_gui.theme()->getFontHeight(ThemeEngine::kFontStyleTooltip) + 2; + + // Make Rect bigger for compensating the shadow + _storedState = g_gui.theme()->storeState(Common::Rect(_x - 5, _y - 5, _x + _w + 5, _y + _h + 5)); + + g_gui.theme()->startBuffering(); + g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0, ThemeEngine::kWidgetBackgroundBorderSmall); + + for (Common::StringArray::const_iterator i = _wrappedLines.begin(); i != _wrappedLines.end(); ++i, ++num) { + g_gui.theme()->drawText(Common::Rect(_x + 1, _y + 1 + num * h, _x + 1 +_w, _y + 1+ (num + 1) * h), *i, ThemeEngine::kStateEnabled, Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, 0, false, ThemeEngine::kFontStyleTooltip, ThemeEngine::kFontColorNormal, false); + } + g_gui.theme()->finishBuffering(); +} + +void Tooltip::reflowLayout() { +} + +void Tooltip::setMouseXY(int x, int y) { + _mouseX = x; + _mouseY = y; +} + +void Tooltip::setVisible(bool state) { + if (state == _visible) + return; + + if (state) { + if (!_guiManager->getTopDialog()) + return; + + Widget *wdg = _guiManager->getTopDialog()->findWidget(_mouseX, _mouseY); + + if (!wdg) + return; + + if (wdg->getTooltip()) { + _visible = state; + + // Cache config values. + // NOTE: we cannot do it in the consturctor + if (_maxWidth == -1) { + _maxWidth = g_gui.xmlEval()->getVar("Globals.Tooltip.MaxWidth", 100); + _xdelta = g_gui.xmlEval()->getVar("Globals.Tooltip.XDelta", 0); + _ydelta = g_gui.xmlEval()->getVar("Globals.Tooltip.YDelta", 0); + } + + const Graphics::Font *tooltipFont = g_gui.theme()->getFont(ThemeEngine::kFontStyleTooltip); + + _wrappedLines.clear(); + _w = tooltipFont->wordWrapText(wdg->getTooltip(), _maxWidth - 4, _wrappedLines); + _h = (tooltipFont->getFontHeight() + 2) * _wrappedLines.size(); + + _x = MIN<int16>(_guiManager->getTopDialog()->_x + _mouseX + _xdelta, g_gui.getWidth() - _w - 3); + _y = MIN<int16>(_guiManager->getTopDialog()->_y + _mouseY + _ydelta, g_gui.getHeight() - _h - 3); + + draw(); + } + } else { + _visible = state; + + g_gui.theme()->restoreState(_storedState); + delete _storedState; + } +} + #pragma mark - -StaticTextWidget::StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &text, Graphics::TextAlign align) - : Widget(boss, x, y, w, h), _align(align) { +StaticTextWidget::StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &text, Graphics::TextAlign align, const char *tooltip) + : Widget(boss, x, y, w, h, tooltip), _align(align) { setFlags(WIDGET_ENABLED); _type = kStaticTextWidget; _label = text; } -StaticTextWidget::StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text) - : Widget(boss, name) { +StaticTextWidget::StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text, const char *tooltip) + : Widget(boss, name, tooltip) { setFlags(WIDGET_ENABLED); _type = kStaticTextWidget; _label = text; @@ -227,16 +349,22 @@ void StaticTextWidget::drawWidget() { #pragma mark - -ButtonWidget::ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, uint32 cmd, uint8 hotkey) - : StaticTextWidget(boss, x, y, w, h, label, Graphics::kTextAlignCenter), CommandSender(boss), - _cmd(cmd), _hotkey(hotkey) { +ButtonWidget::ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey) + : StaticTextWidget(boss, x, y, w, h, cleanupHotkey(label), Graphics::kTextAlignCenter, tooltip), CommandSender(boss), + _cmd(cmd) { + + if (hotkey == 0) + _hotkey = parseHotkey(label); + setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG); _type = kButtonWidget; } -ButtonWidget::ButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, uint32 cmd, uint8 hotkey) - : StaticTextWidget(boss, name, label), CommandSender(boss), - _cmd(cmd), _hotkey(hotkey) { +ButtonWidget::ButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey) + : StaticTextWidget(boss, name, cleanupHotkey(label), tooltip), CommandSender(boss), + _cmd(cmd) { + if (hotkey == 0) + _hotkey = parseHotkey(label); setFlags(WIDGET_ENABLED/* | WIDGET_BORDER*/ | WIDGET_CLEARBG); _type = kButtonWidget; } @@ -252,14 +380,14 @@ void ButtonWidget::drawWidget() { #pragma mark - -CheckboxWidget::CheckboxWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, uint32 cmd, uint8 hotkey) - : ButtonWidget(boss, x, y, w, h, label, cmd, hotkey), _state(false) { +CheckboxWidget::CheckboxWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey) + : ButtonWidget(boss, x, y, w, h, label, tooltip, cmd, hotkey), _state(false) { setFlags(WIDGET_ENABLED); _type = kCheckboxWidget; } -CheckboxWidget::CheckboxWidget(GuiObject *boss, const Common::String &name, const Common::String &label, uint32 cmd, uint8 hotkey) - : ButtonWidget(boss, name, label, cmd, hotkey), _state(false) { +CheckboxWidget::CheckboxWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip, uint32 cmd, uint8 hotkey) + : ButtonWidget(boss, name, label, tooltip, cmd, hotkey), _state(false) { setFlags(WIDGET_ENABLED); _type = kCheckboxWidget; } @@ -284,16 +412,84 @@ void CheckboxWidget::drawWidget() { } #pragma mark - +RadiobuttonGroup::RadiobuttonGroup(GuiObject *boss, uint32 cmd) : CommandSender(boss) { + _value = -1; + _cmd = cmd; +} + +void RadiobuttonGroup::setValue(int value) { + Common::Array<RadiobuttonWidget *>::iterator button = _buttons.begin(); + while (button != _buttons.end()) { + (*button)->setState((*button)->getValue() == value, false); + + button++; + } + + _value = value; + + sendCommand(_cmd, _value); +} + +void RadiobuttonGroup::setEnabled(bool ena) { + Common::Array<RadiobuttonWidget *>::iterator button = _buttons.begin(); + while (button != _buttons.end()) { + (*button)->setEnabled(ena); + + button++; + } +} + +#pragma mark - + +RadiobuttonWidget::RadiobuttonWidget(GuiObject *boss, int x, int y, int w, int h, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip, uint8 hotkey) + : ButtonWidget(boss, x, y, w, h, label, tooltip, 0, hotkey), _state(false), _value(value), _group(group) { + setFlags(WIDGET_ENABLED); + _type = kRadiobuttonWidget; + _group->addButton(this); +} + +RadiobuttonWidget::RadiobuttonWidget(GuiObject *boss, const Common::String &name, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip, uint8 hotkey) + : ButtonWidget(boss, name, label, tooltip, 0, hotkey), _state(false), _value(value), _group(group) { + setFlags(WIDGET_ENABLED); + _type = kRadiobuttonWidget; + _group->addButton(this); +} + +void RadiobuttonWidget::handleMouseUp(int x, int y, int button, int clickCount) { + if (isEnabled() && x >= 0 && x < _w && y >= 0 && y < _h) { + toggleState(); + } +} + +void RadiobuttonWidget::setState(bool state, bool setGroup) { + if (setGroup) { + _group->setValue(_value); + return; + } + + if (_state != state) { + _state = state; + //_flags ^= WIDGET_INV_BORDER; + draw(); + } + sendCommand(_cmd, _state); +} + +void RadiobuttonWidget::drawWidget() { + g_gui.theme()->drawRadiobutton(Common::Rect(_x, _y, _x+_w, _y+_h), _label, _state, Widget::_state); +} + +#pragma mark - -SliderWidget::SliderWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd) - : Widget(boss, x, y, w, h), CommandSender(boss), +SliderWidget::SliderWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip, uint32 cmd) + : Widget(boss, x, y, w, h, tooltip), CommandSender(boss), _cmd(cmd), _value(0), _oldValue(0), _valueMin(0), _valueMax(100), _isDragging(false) { setFlags(WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_CLEARBG); _type = kSliderWidget; } -SliderWidget::SliderWidget(GuiObject *boss, const Common::String &name, uint32 cmd) - : Widget(boss, name), CommandSender(boss), +SliderWidget::SliderWidget(GuiObject *boss, const Common::String &name, const char *tooltip, uint32 cmd) + : Widget(boss, name, tooltip), CommandSender(boss), _cmd(cmd), _value(0), _oldValue(0), _valueMin(0), _valueMax(100), _isDragging(false) { setFlags(WIDGET_ENABLED | WIDGET_TRACK_MOUSE | WIDGET_CLEARBG); _type = kSliderWidget; @@ -365,14 +561,14 @@ int SliderWidget::posToValue(int pos) { #pragma mark - -GraphicsWidget::GraphicsWidget(GuiObject *boss, int x, int y, int w, int h) - : Widget(boss, x, y, w, h), _gfx(), _alpha(256), _transparency(false) { +GraphicsWidget::GraphicsWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip) + : Widget(boss, x, y, w, h, tooltip), _gfx(), _alpha(256), _transparency(false) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG); _type = kGraphicsWidget; } -GraphicsWidget::GraphicsWidget(GuiObject *boss, const Common::String &name) - : Widget(boss, name), _gfx(), _alpha(256), _transparency(false) { +GraphicsWidget::GraphicsWidget(GuiObject *boss, const Common::String &name, const char *tooltip) + : Widget(boss, name, tooltip), _gfx(), _alpha(256), _transparency(false) { setFlags(WIDGET_ENABLED | WIDGET_CLEARBG); _type = kGraphicsWidget; } @@ -387,6 +583,11 @@ void GraphicsWidget::setGfx(const Graphics::Surface *gfx) { if (!gfx || !gfx->pixels) return; + if (gfx->w > _w || gfx->h > _h) { + warning("GraphicsWidget has size %dx%d, but a surface with %dx%d is to be set", _w, _h, gfx->w, gfx->h); + return; + } + // TODO: add conversion to OverlayColor _gfx.copyFrom(*gfx); } @@ -400,7 +601,7 @@ void GraphicsWidget::setGfx(int w, int h, int r, int g, int b) { _gfx.free(); _gfx.create(w, h, sizeof(OverlayColor)); - OverlayColor *dst = (OverlayColor*)_gfx.pixels; + OverlayColor *dst = (OverlayColor *)_gfx.pixels; Graphics::PixelFormat overlayFormat = g_system->getOverlayFormat(); OverlayColor fillCol = overlayFormat.RGBToColor(r, g, b); while (h--) { @@ -411,8 +612,12 @@ void GraphicsWidget::setGfx(int w, int h, int r, int g, int b) { } void GraphicsWidget::drawWidget() { - if (sizeof(OverlayColor) == _gfx.bytesPerPixel && _gfx.pixels) - g_gui.theme()->drawSurface(Common::Rect(_x, _y, _x+_w, _y+_h), _gfx, _state, _alpha, _transparency); + if (sizeof(OverlayColor) == _gfx.bytesPerPixel && _gfx.pixels) { + const int x = _x + (_w - _gfx.w) / 2; + const int y = _y + (_h - _gfx.h) / 2; + + g_gui.theme()->drawSurface(Common::Rect(x, y, x + _gfx.w, y + _gfx.h), _gfx, _state, _alpha, _transparency); + } } #pragma mark - diff --git a/gui/widget.h b/gui/widget.h index ebadc53241..7b5fe9253f 100644 --- a/gui/widget.h +++ b/gui/widget.h @@ -27,6 +27,7 @@ #include "common/scummsys.h" #include "common/str.h" +#include "common/str-array.h" #include "common/keyboard.h" #include "graphics/surface.h" #include "gui/object.h" @@ -62,6 +63,7 @@ enum { kEditTextWidget = 'EDIT', kButtonWidget = 'BTTN', kCheckboxWidget = 'CHKB', + kRadiobuttonWidget = 'RDBT', kSliderWidget = 'SLDE', kListWidget = 'LIST', kScrollBarWidget = 'SCRB', @@ -85,6 +87,7 @@ protected: uint16 _id; bool _hasFocus; ThemeEngine::WidgetStateInfo _state; + const char *_tooltip; private: uint16 _flags; @@ -94,8 +97,8 @@ public: static Widget *findWidgetInChain(Widget *start, const char *name); public: - Widget(GuiObject *boss, int x, int y, int w, int h); - Widget(GuiObject *boss, const Common::String &name); + Widget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip = 0); + Widget(GuiObject *boss, const Common::String &name, const char *tooltip = 0); virtual ~Widget(); void init(); @@ -135,6 +138,11 @@ public: void setVisible(bool e); bool isVisible() const; + uint8 parseHotkey(const Common::String &label); + Common::String cleanupHotkey(const Common::String &label); + + const char *getTooltip() const { return _tooltip; } + protected: void updateState(int oldFlags, int newFlags); @@ -151,14 +159,39 @@ protected: void handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { assert(_boss); _boss->handleCommand(sender, cmd, data); } }; +class GuiManager; + +class Tooltip : public GuiObject { +public: + Tooltip(GuiManager *guiManager); + + bool isVisible() const { return _visible; } + void draw(); + void reflowLayout(); + void releaseFocus() {} + void setVisible(bool state); + void setMouseXY(int x, int y); + +protected: + Common::String _text; + GuiManager *_guiManager; + bool _visible; + int _mouseX, _mouseY; + int _maxWidth; + int _xdelta, _ydelta; + + Common::StringArray _wrappedLines; + ThemeEngine::StoredState *_storedState; +}; + /* StaticTextWidget */ class StaticTextWidget : public Widget { protected: Common::String _label; Graphics::TextAlign _align; public: - StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &text, Graphics::TextAlign align); - StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text); + StaticTextWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &text, Graphics::TextAlign align, const char *tooltip = 0); + StaticTextWidget(GuiObject *boss, const Common::String &name, const Common::String &text, const char *tooltip = 0); void setValue(int value); void setLabel(const Common::String &label); const Common::String &getLabel() const { return _label; } @@ -176,8 +209,8 @@ protected: uint32 _cmd; uint8 _hotkey; public: - ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, uint32 cmd = 0, uint8 hotkey = 0); - ButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, uint32 cmd = 0, uint8 hotkey = 0); + ButtonWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0); + ButtonWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0); void setCmd(uint32 cmd) { _cmd = cmd; } uint32 getCmd() const { return _cmd; } @@ -195,8 +228,8 @@ class CheckboxWidget : public ButtonWidget { protected: bool _state; public: - CheckboxWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, uint32 cmd = 0, uint8 hotkey = 0); - CheckboxWidget(GuiObject *boss, const Common::String &name, const Common::String &label, uint32 cmd = 0, uint8 hotkey = 0); + CheckboxWidget(GuiObject *boss, int x, int y, int w, int h, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0); + CheckboxWidget(GuiObject *boss, const Common::String &name, const Common::String &label, const char *tooltip = 0, uint32 cmd = 0, uint8 hotkey = 0); void handleMouseUp(int x, int y, int button, int clickCount); virtual void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } @@ -210,6 +243,55 @@ protected: void drawWidget(); }; +class RadiobuttonWidget; + +class RadiobuttonGroup : public CommandSender { +public: + RadiobuttonGroup(GuiObject *boss, uint32 cmd = 0); + ~RadiobuttonGroup() {} + + void addButton(RadiobuttonWidget *button) { _buttons.push_back(button); } + Common::Array<RadiobuttonWidget *> getButtonList() const { return _buttons; } + + void setValue(int state); + int getValue() const { return _value; } + + void setEnabled(bool ena); + + void setCmd(uint32 cmd) { _cmd = cmd; } + uint32 getCmd() const { return _cmd; } + +protected: + Common::Array<RadiobuttonWidget *> _buttons; + int _value; + uint32 _cmd; +}; + +/* RadiobuttonWidget */ +class RadiobuttonWidget : public ButtonWidget { +protected: + bool _state; + int _value; + +public: + RadiobuttonWidget(GuiObject *boss, int x, int y, int w, int h, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip = 0, uint8 hotkey = 0); + RadiobuttonWidget(GuiObject *boss, const Common::String &name, RadiobuttonGroup *group, int value, const Common::String &label, const char *tooltip = 0, uint8 hotkey = 0); + + void handleMouseUp(int x, int y, int button, int clickCount); + virtual void handleMouseEntered(int button) { setFlags(WIDGET_HILITED); draw(); } + virtual void handleMouseLeft(int button) { clearFlags(WIDGET_HILITED); draw(); } + + void setState(bool state, bool setGroup = true); + void toggleState() { setState(!_state); } + bool getState() const { return _state; } + int getValue() const { return _value; } + +protected: + void drawWidget(); + + RadiobuttonGroup *_group; +}; + /* SliderWidget */ class SliderWidget : public Widget, public CommandSender { protected: @@ -219,8 +301,8 @@ protected: bool _isDragging; uint _labelWidth; public: - SliderWidget(GuiObject *boss, int x, int y, int w, int h, uint32 cmd = 0); - SliderWidget(GuiObject *boss, const Common::String &name, uint32 cmd = 0); + SliderWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip = 0, uint32 cmd = 0); + SliderWidget(GuiObject *boss, const Common::String &name, const char *tooltip = 0, uint32 cmd = 0); void setCmd(uint32 cmd) { _cmd = cmd; } uint32 getCmd() const { return _cmd; } @@ -251,8 +333,8 @@ protected: /* GraphicsWidget */ class GraphicsWidget : public Widget { public: - GraphicsWidget(GuiObject *boss, int x, int y, int w, int h); - GraphicsWidget(GuiObject *boss, const Common::String &name); + GraphicsWidget(GuiObject *boss, int x, int y, int w, int h, const char *tooltip = 0); + GraphicsWidget(GuiObject *boss, const Common::String &name, const char *tooltip = 0); ~GraphicsWidget(); void setGfx(const Graphics::Surface *gfx); diff --git a/po/POTFILES b/po/POTFILES new file mode 100644 index 0000000000..28ca60d31b --- /dev/null +++ b/po/POTFILES @@ -0,0 +1,45 @@ +#TODO: help_string & usage_string: + +gui/about.cpp +gui/browser.cpp +gui/chooser.cpp +gui/error.cpp +gui/GuiManager.cpp +gui/KeysDialog.cpp +gui/launcher.cpp +gui/massadd.cpp +gui/options.cpp +gui/saveload.cpp +gui/themebrowser.cpp +gui/ThemeEngine.cpp + +base/main.cpp + +common/error.cpp +common/util.cpp + +engines/dialogs.cpp +engines/scumm/dialogs.cpp +engines/mohawk/dialogs.cpp + +sound/fmopl.cpp +sound/musicplugin.cpp +sound/null.h +sound/null.cpp +sound/softsynth/adlib.cpp +sound/softsynth/mt32.cpp +sound/softsynth/pcspk.cpp +sound/softsynth/ym2612.cpp + +backends/keymapper/remap-dialog.cpp +backends/midi/windows.cpp +backends/platform/ds/arm9/source/dsoptions.cpp +backends/platform/iphone/osys_events.cpp +backends/platform/sdl/graphics.cpp +backends/platform/symbian/src/SymbianActions.cpp +backends/platform/symbian/src/SymbianOS.cpp +backends/platform/wii/options.cpp +backends/platform/wince/CEActionsPocket.cpp +backends/platform/wince/CEActionsSmartphone.cpp +backends/platform/wince/CELauncherDialog.cpp +backends/platform/wince/wince-sdl.cpp diff --git a/po/ca_ES.po b/po/ca_ES.po new file mode 100644 index 0000000000..7905fbdf16 --- /dev/null +++ b/po/ca_ES.po @@ -0,0 +1,1447 @@ +# Catalan translation for ScummVM. +# Copyright (C) 2007-2010 ScummVM +# This file is distributed under the same license as the ScummVM package. +# Jordi Vilalta Prat <jvprat@jvprat.com>, 2007-2010. +# +msgid "" +msgstr "" +"Project-Id-Version: ScummVM 1.2.0svn\n" +"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n" +"POT-Creation-Date: 2010-07-12 17:44+0200\n" +"PO-Revision-Date: 2010-06-26 16:45+0100\n" +"Last-Translator: Jordi Vilalta Prat <jvprat@gmail.com>\n" +"Language-Team: Catalan <scummvm-devel@lists.sf.net>\n" +"Language: Catalan\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" + +#: gui/about.cpp:96 +#, c-format +msgid "(built on %s)" +msgstr "(compilat el %s)" + +#: gui/about.cpp:103 +msgid "Features compiled in:" +msgstr "Característiques compilades:" + +#: gui/about.cpp:112 +msgid "Available engines:" +msgstr "Motors disponibles:" + +#: gui/browser.cpp:69 +msgid "Go up" +msgstr "Amunt" + +#: gui/browser.cpp:69 +msgid "Go to previous directory level" +msgstr "Torna al nivell de directoris anterior" + +#: gui/browser.cpp:70 gui/chooser.cpp:49 gui/KeysDialog.cpp:46 +#: gui/launcher.cpp:266 gui/massadd.cpp:95 gui/options.cpp:972 +#: gui/saveload.cpp:65 gui/saveload.cpp:157 gui/themebrowser.cpp:56 +#: backends/platform/wii/options.cpp:48 +msgid "Cancel" +msgstr "Cancel·la" + +#: gui/browser.cpp:71 gui/chooser.cpp:50 gui/themebrowser.cpp:57 +msgid "Choose" +msgstr "Escull" + +#: gui/GuiManager.cpp:102 backends/keymapper/remap-dialog.cpp:54 +msgid "Close" +msgstr "Tanca" + +#: gui/GuiManager.cpp:105 +msgid "Mouse click" +msgstr "Clic del ratolí" + +#: gui/GuiManager.cpp:108 base/main.cpp:285 +msgid "Display keyboard" +msgstr "Mostra el teclat" + +#: gui/GuiManager.cpp:111 base/main.cpp:288 +msgid "Remap keys" +msgstr "Remapeja les tecles" + +#: gui/KeysDialog.cpp:44 +msgid "Map" +msgstr "Mapeja" + +#: gui/KeysDialog.cpp:45 gui/launcher.cpp:267 gui/launcher.cpp:873 +#: gui/launcher.cpp:877 gui/massadd.cpp:92 gui/options.cpp:973 +#: backends/platform/wii/options.cpp:47 +#: backends/platform/wince/CELauncherDialog.cpp:56 +msgid "OK" +msgstr "D'acord" + +#: gui/KeysDialog.cpp:52 +msgid "Select an action and click 'Map'" +msgstr "Seleccioneu una acció i cliqueu 'Mapeja'" + +#: gui/KeysDialog.cpp:83 gui/KeysDialog.cpp:105 gui/KeysDialog.cpp:144 +#, c-format +msgid "Associated key : %s" +msgstr "Tecla associada : %s" + +#: gui/KeysDialog.cpp:85 gui/KeysDialog.cpp:107 gui/KeysDialog.cpp:146 +#, c-format +msgid "Associated key : none" +msgstr "Tecla associada : cap" + +#: gui/KeysDialog.cpp:93 +msgid "Please select an action" +msgstr "Seleccioneu una acció" + +#: gui/KeysDialog.cpp:109 +msgid "Press the key to associate" +msgstr "Premeu la tecla a associar" + +#: gui/KeysDialog.cpp:148 +msgid "Choose an action to map" +msgstr "Sel·leccioneu una acció per mapejar" + +#: gui/launcher.cpp:170 +msgid "Game" +msgstr "Joc" + +#: gui/launcher.cpp:173 +msgid "ID:" +msgstr "Identificador:" + +#: gui/launcher.cpp:173 gui/launcher.cpp:174 +msgid "" +"Short game identifier used for referring to savegames and running the game " +"from the command line" +msgstr "" +"Identificador de joc curt utilitzat per referir-se a les partides i per " +"executar el joc des de la línia de comandes" + +#: gui/launcher.cpp:177 +msgid "Name:" +msgstr "Nom:" + +#: gui/launcher.cpp:177 gui/launcher.cpp:178 +msgid "Full title of the game" +msgstr "Títol complet del joc" + +#: gui/launcher.cpp:181 +msgid "Language:" +msgstr "Idioma:" + +#: gui/launcher.cpp:181 gui/launcher.cpp:182 +msgid "" +"Language of the game. This will not turn your Spanish game version into " +"English" +msgstr "" +"Idioma del joc. Això no convertirà la vostra versió Espanyola del joc a " +"Anglès" + +#: gui/launcher.cpp:183 gui/launcher.cpp:194 gui/options.cpp:80 +#: gui/options.cpp:617 gui/options.cpp:627 gui/options.cpp:943 +#: sound/null.cpp:42 +msgid "<default>" +msgstr "<per defecte>" + +#: gui/launcher.cpp:192 +msgid "Platform:" +msgstr "Plataforma:" + +#: gui/launcher.cpp:192 gui/launcher.cpp:193 +msgid "Platform the game was originally designed for" +msgstr "Plataforma per la que el joc es va dissenyar originalment" + +#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867 +msgid "Graphics" +msgstr "Gràfics" + +#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867 +msgid "GFX" +msgstr "GFX" + +#: gui/launcher.cpp:206 +msgid "Override global graphic settings" +msgstr "Fer canvis sobre les opcions globals de gràfics" + +#: gui/launcher.cpp:213 gui/options.cpp:873 +msgid "Audio" +msgstr "Àudio" + +#: gui/launcher.cpp:215 +msgid "Override global audio settings" +msgstr "Fer canvis sobre les opcions globals d'àudio" + +#: gui/launcher.cpp:223 gui/options.cpp:877 +msgid "Volume" +msgstr "Volum" + +#: gui/launcher.cpp:225 +msgid "Override global volume settings" +msgstr "Fer canvis sobre les opcions globals de volum" + +#: gui/launcher.cpp:232 gui/options.cpp:885 +msgid "MIDI" +msgstr "MIDI" + +#: gui/launcher.cpp:234 +msgid "Override global MIDI settings" +msgstr "Fer canvis sobre les opcions globals de MIDI" + +#: gui/launcher.cpp:244 gui/options.cpp:891 +msgid "Paths" +msgstr "Camins" + +#: gui/launcher.cpp:250 +msgid "Game Path:" +msgstr "Camí del Joc:" + +#: gui/launcher.cpp:254 gui/options.cpp:904 +msgid "Extra Path:" +msgstr "Camí Extra:" + +#: gui/launcher.cpp:254 gui/launcher.cpp:255 +msgid "Specifies path to additional data used the game" +msgstr "Especifica el camí de dades addicionals utilitzades pel joc" + +#: gui/launcher.cpp:258 +msgid "Save Path:" +msgstr "Camí de les Partides:" + +#: gui/launcher.cpp:258 gui/launcher.cpp:259 gui/options.cpp:898 +#: gui/options.cpp:899 +msgid "Specifies where your savegames are put" +msgstr "Especifica on es desaran les partides" + +#: gui/launcher.cpp:275 gui/launcher.cpp:353 gui/launcher.cpp:398 +#: gui/options.cpp:245 gui/options.cpp:400 gui/options.cpp:486 +#: gui/options.cpp:545 gui/options.cpp:706 gui/options.cpp:902 +#: gui/options.cpp:905 gui/options.cpp:909 gui/options.cpp:996 +#: gui/options.cpp:1002 gui/options.cpp:1008 gui/options.cpp:1016 +#: gui/options.cpp:1040 gui/options.cpp:1044 gui/options.cpp:1050 +#: gui/options.cpp:1057 gui/options.cpp:1156 +msgid "None" +msgstr "Cap" + +#: gui/launcher.cpp:280 gui/launcher.cpp:357 +#: backends/platform/wii/options.cpp:56 +msgid "Default" +msgstr "Per defecte" + +#: gui/launcher.cpp:391 gui/options.cpp:1150 +msgid "Select SoundFont" +msgstr "Seleccioneu el fitxer SoundFont" + +#: gui/launcher.cpp:410 gui/launcher.cpp:548 +msgid "Select directory with game data" +msgstr "Seleccioneu el directori amb les dades del joc" + +#: gui/launcher.cpp:428 +msgid "Select additional game directory" +msgstr "Seleccioneu el directori addicional del joc" + +#: gui/launcher.cpp:440 +msgid "Select directory for saved games" +msgstr "Seleccioneu el directori de les partides desades" + +#: gui/launcher.cpp:459 +msgid "This game ID is already taken. Please choose another one." +msgstr "" +"Aquest identificador de joc ja està usat. Si us plau, trieu-ne un altre." + +#: gui/launcher.cpp:500 engines/dialogs.cpp:113 +msgid "~Q~uit" +msgstr "~T~anca" + +#: gui/launcher.cpp:500 +msgid "Quit ScummVM" +msgstr "Surt de ScummVM" + +#: gui/launcher.cpp:501 +msgid "A~b~out..." +msgstr "~Q~uant a..." + +#: gui/launcher.cpp:501 +msgid "About ScummVM" +msgstr "Quant a ScummVM" + +#: gui/launcher.cpp:502 +msgid "~O~ptions..." +msgstr "~O~pcions..." + +#: gui/launcher.cpp:502 +msgid "Change global ScummVM options" +msgstr "Canvia les opcions globals de ScummVM" + +#: gui/launcher.cpp:504 +msgid "~S~tart" +msgstr "~I~nicia" + +#: gui/launcher.cpp:504 +msgid "Start selected game" +msgstr "Iniciant el joc seleccionat" + +#: gui/launcher.cpp:507 +msgid "~L~oad..." +msgstr "~C~arrega..." + +#: gui/launcher.cpp:507 +msgid "Load savegame for selected game" +msgstr "Carrega una partida pel joc seleccionat" + +#: gui/launcher.cpp:511 +msgid "~A~dd Game..." +msgstr "~A~fegeix Joc..." + +#: gui/launcher.cpp:511 +msgid "Hold Shift for Mass Add" +msgstr "Mantingueu premut Shift per a l'Addició Massiva" + +#: gui/launcher.cpp:513 +msgid "~E~dit Game..." +msgstr "~E~dita Joc..." + +#: gui/launcher.cpp:513 +msgid "Change game options" +msgstr "Canvia les opcions del joc" + +#: gui/launcher.cpp:515 +msgid "~R~emove Game" +msgstr "~S~uprimeix Joc" + +#: gui/launcher.cpp:515 +msgid "Remove game from the list. The game data files stay intact" +msgstr "" +"Elimina un joc de la llista. Els fitxers de dades del joc es mantenen " +"intactes" + +#: gui/launcher.cpp:522 +msgid "Search in game list" +msgstr "Cerca a la llista de jocs" + +#: gui/launcher.cpp:526 gui/launcher.cpp:1037 +msgid "Search:" +msgstr "Cerca:" + +#: gui/launcher.cpp:529 gui/options.cpp:707 +msgid "Clear value" +msgstr "Neteja el valor" + +#: gui/launcher.cpp:551 engines/dialogs.cpp:117 +msgid "Load game:" +msgstr "Carrega partida:" + +#: gui/launcher.cpp:551 engines/dialogs.cpp:117 +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Load" +msgstr "Carrega" + +#: gui/launcher.cpp:660 +msgid "" +"Do you really want to run the mass game detector? This could potentially add " +"a huge number of games." +msgstr "" +"Esteu segur que voleu executar el detector massiu de jocs? Això pot afegir " +"una gran quantitat de jocs." + +#: gui/launcher.cpp:661 gui/launcher.cpp:810 +#: backends/platform/symbian/src/SymbianOS.cpp:446 +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "Yes" +msgstr "Sí" + +#: gui/launcher.cpp:661 gui/launcher.cpp:810 +#: backends/platform/symbian/src/SymbianOS.cpp:446 +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "No" +msgstr "No" + +#: gui/launcher.cpp:708 +msgid "ScummVM couldn't open the specified directory!" +msgstr "ScummVM no ha pogut obrir el directori especificat!" + +#: gui/launcher.cpp:720 +msgid "ScummVM could not find any game in the specified directory!" +msgstr "ScummVM no ha pogut trobar cap joc al directori especificat!" + +#: gui/launcher.cpp:734 +msgid "Pick the game:" +msgstr "Seleccioneu el joc:" + +#: gui/launcher.cpp:810 +msgid "Do you really want to remove this game configuration?" +msgstr "Realment voleu suprimir la configuració d'aquest joc?" + +#: gui/launcher.cpp:873 +msgid "This game does not support loading games from the launcher." +msgstr "Aquest joc no suporta la càrrega de partides des del llançador." + +#: gui/launcher.cpp:877 +msgid "ScummVM could not find any engine capable of running the selected game!" +msgstr "" +"ScummVM no ha pogut trobar cap motor capaç d'executar el joc seleccionat!" + +#: gui/launcher.cpp:989 +msgid "Mass Add..." +msgstr "Addició Massiva..." + +#: gui/launcher.cpp:990 +msgid "Add Game..." +msgstr "Afegeix Joc..." + +#: gui/massadd.cpp:79 gui/massadd.cpp:82 +msgid "... progress ..." +msgstr "... progrés ..." + +#: gui/massadd.cpp:244 +msgid "Scan complete!" +msgstr "S'ha acabat la cerca!" + +#: gui/massadd.cpp:247 +#, c-format +msgid "Discovered %d new games." +msgstr "S'han descobert %d jocs nous." + +#: gui/massadd.cpp:251 +#, c-format +msgid "Scanned %d directories ..." +msgstr "S'han cercat %d directoris ..." + +#: gui/massadd.cpp:254 +#, c-format +msgid "Discovered %d new games ..." +msgstr "S'han descobert %d jocs nous ..." + +#: gui/options.cpp:78 +msgid "Never" +msgstr "Mai" + +#: gui/options.cpp:78 +msgid "every 5 mins" +msgstr "cada 5 minuts" + +#: gui/options.cpp:78 +msgid "every 10 mins" +msgstr "cada 10 minuts" + +#: gui/options.cpp:78 +msgid "every 15 mins" +msgstr "cada 15 minuts" + +#: gui/options.cpp:78 +msgid "every 30 mins" +msgstr "cada 30 minuts" + +#: gui/options.cpp:80 +msgid "8 kHz" +msgstr "8 kHz" + +#: gui/options.cpp:80 +msgid "11kHz" +msgstr "11kHz" + +#: gui/options.cpp:80 +msgid "22 kHz" +msgstr "22 kHz" + +#: gui/options.cpp:80 +msgid "44 kHz" +msgstr "44 kHz" + +#: gui/options.cpp:80 +msgid "48 kHz" +msgstr "48 kHz" + +#: gui/options.cpp:614 +msgid "Graphics mode:" +msgstr "Mode gràfic:" + +#: gui/options.cpp:625 +msgid "Render mode:" +msgstr "Mode de pintat:" + +#: gui/options.cpp:625 gui/options.cpp:626 +msgid "Special dithering modes supported by some games" +msgstr "Modes de dispersió especials suportats per alguns jocs" + +#: gui/options.cpp:635 +msgid "Fullscreen mode" +msgstr "Mode pantalla completa" + +#: gui/options.cpp:638 +msgid "Aspect ratio correction" +msgstr "Correcció del rati d'aspecte" + +#: gui/options.cpp:638 +msgid "Correct aspect ratio for 320x200 games" +msgstr "Corregeix la relació d'aspecte per jocs de 320x200" + +#: gui/options.cpp:645 +msgid "Preferred Device:" +msgstr "Dispositiu Preferit:" + +#: gui/options.cpp:645 +#, fuzzy +msgid "Music Device:" +msgstr "Dispositiu GM:" + +#: gui/options.cpp:645 +msgid "Specifies preferred sound device or sound card emulator" +msgstr "Especifica el dispositiu de so o l'emulador de tarja de so preferit" + +#: gui/options.cpp:645 gui/options.cpp:646 +msgid "Specifies output sound device or sound card emulator" +msgstr "Especifica el dispositiu de so o l'emulador de tarja de so de sortida" + +#: gui/options.cpp:648 +#, fuzzy +msgid "MT-32 Device:" +msgstr "Dispositiu MT32:" + +#: gui/options.cpp:648 +msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output" +msgstr "" +"Especifica el dispositiu de so per defecte per a la sortida de Roland MT-32/" +"LAPC1/CM32l/CM64" + +#: gui/options.cpp:650 +msgid "GM Device:" +msgstr "Dispositiu GM:" + +#: gui/options.cpp:650 +msgid "Specifies default sound device for General MIDI output" +msgstr "" +"Especifica el dispositiu de so per defecte per a la sortida General MIDI" + +#: gui/options.cpp:682 +msgid "AdLib emulator:" +msgstr "Emulador d'AdLib:" + +#: gui/options.cpp:682 gui/options.cpp:683 +msgid "AdLib is used for music in many games" +msgstr "AdLib s'utilitza per la música de molts jocs" + +#: gui/options.cpp:693 +msgid "Output rate:" +msgstr "Freqüència de sortida:" + +#: gui/options.cpp:693 gui/options.cpp:694 +msgid "" +"Higher value specifies better sound quality but may be not supported by your " +"soundcard" +msgstr "" +"Valors més alts especifiquen millor qualitat de so però pot ser que la " +"vostra tarja de so no ho suporti" + +#: gui/options.cpp:705 +msgid "SoundFont:" +msgstr "Fitxer SoundFont:" + +#: gui/options.cpp:705 gui/options.cpp:706 +msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity" +msgstr "Algunes targes de so, Fluidsynth i Timidity suporten SoundFont" + +#: gui/options.cpp:710 +msgid "Mixed AdLib/MIDI mode" +msgstr "Mode combinat AdLib/MIDI" + +#: gui/options.cpp:710 +msgid "Use both MIDI and AdLib sound generation" +msgstr "Utilitza MIDI i la generació de so AdLib alhora" + +#: gui/options.cpp:713 +msgid "True Roland MT-32 (disable GM emulation)" +msgstr "Roland MT-32 real (desactiva l'emulació GM)" + +#: gui/options.cpp:713 +msgid "" +"Check if you want to use your real hardware Roland-compatible sound device " +"connected to your computer" +msgstr "" +"Marqueu si voleu utilitzar el vostre dispositiu hardware real de so " +"compatible amb Roland connectat al vostre ordinador" + +#: gui/options.cpp:716 +msgid "Enable Roland GS Mode" +msgstr "Activa el Mode Roland GS" + +#: gui/options.cpp:716 +msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack" +msgstr "" +"Desactiva la conversió General MIDI pels jocs que tenen banda sonora per a " +"Roland MT-32" + +#: gui/options.cpp:719 +msgid "MIDI gain:" +msgstr "Guany MIDI:" + +#: gui/options.cpp:732 +msgid "Text and Speech:" +msgstr "Text i Veus:" + +#: gui/options.cpp:737 gui/options.cpp:743 +msgid "Speech" +msgstr "Veus" + +#: gui/options.cpp:738 gui/options.cpp:744 +msgid "Subtitles" +msgstr "Subtítols" + +#: gui/options.cpp:739 gui/options.cpp:745 +msgid "Both" +msgstr "Ambdós" + +#: gui/options.cpp:743 +msgid "Spch" +msgstr "Veus" + +#: gui/options.cpp:744 +msgid "Subs" +msgstr "Subt" + +#: gui/options.cpp:745 +msgid "Show subtitles and play speech" +msgstr "Mostra els subtítols i reprodueix la veu" + +#: gui/options.cpp:749 +msgid "Subtitle speed:" +msgstr "Velocitat dels subtítols:" + +#: gui/options.cpp:761 +msgid "Music volume:" +msgstr "Volum de la música:" + +#: gui/options.cpp:768 +msgid "Mute All" +msgstr "Silenciar tot" + +#: gui/options.cpp:771 +msgid "SFX volume:" +msgstr "Volum dels efectes:" + +#: gui/options.cpp:771 gui/options.cpp:772 +msgid "Special sound effects volume" +msgstr "Volum dels sons d'efectes especials" + +#: gui/options.cpp:778 +msgid "Speech volume:" +msgstr "Volum de la veu:" + +#: gui/options.cpp:898 +msgid "Save Path: " +msgstr "Camí de les Partides: " + +#: gui/options.cpp:901 +msgid "Theme Path:" +msgstr "Camí dels Temes:" + +#: gui/options.cpp:904 gui/options.cpp:905 +msgid "Specifies path to additional data used by all games or ScummVM" +msgstr "" +"Especifica el camí de les dades addicionals utilitzades per tots els jocs o " +"pel ScummVM" + +#: gui/options.cpp:908 +msgid "Plugins Path:" +msgstr "Camí dels connectors:" + +#: gui/options.cpp:913 +msgid "Misc" +msgstr "Misc" + +#: gui/options.cpp:915 +msgid "Theme:" +msgstr "Tema:" + +#: gui/options.cpp:919 +msgid "GUI Renderer:" +msgstr "Mode de pintat de la interfície d'usuari:" + +#: gui/options.cpp:925 +msgid "Autosave:" +msgstr "Desat automàtic:" + +#: gui/options.cpp:933 +msgid "Keys" +msgstr "Tecles" + +#: gui/options.cpp:940 +msgid "GUI Language:" +msgstr "Idioma de la interfície d'usuari:" + +#: gui/options.cpp:940 +msgid "Language of ScummVM GUI" +msgstr "Idioma de la interfície d'usuari de ScummVM" + +#: gui/options.cpp:945 +msgid "English" +msgstr "Anglès" + +#: gui/options.cpp:1089 +msgid "You have to restart ScummVM to take the effect." +msgstr "Heu de reiniciar ScummVM perquè tots els canvis tingui efecte." + +#: gui/options.cpp:1102 +msgid "Select directory for savegames" +msgstr "Seleccioneu el directori de les partides desades" + +#: gui/options.cpp:1109 +msgid "The chosen directory cannot be written to. Please select another one." +msgstr "" +"No es pot escriure al directori seleccionat. Si us plau, escolliu-ne un " +"altre." + +#: gui/options.cpp:1118 +msgid "Select directory for GUI themes" +msgstr "Seleccioneu el directori dels temes de la Interfície d'Usuari" + +#: gui/options.cpp:1128 +msgid "Select directory for extra files" +msgstr "Seleccioneu el directori dels fitxers extra" + +#: gui/options.cpp:1139 +msgid "Select directory for plugins" +msgstr "Seleccioneu el directori dels connectors" + +#: gui/saveload.cpp:60 gui/saveload.cpp:241 +msgid "No date saved" +msgstr "No hi ha data desada" + +#: gui/saveload.cpp:61 gui/saveload.cpp:242 +msgid "No time saved" +msgstr "No hi ha hora desada" + +#: gui/saveload.cpp:62 gui/saveload.cpp:243 +msgid "No playtime saved" +msgstr "No hi ha temps de joc desat" + +#: gui/saveload.cpp:69 gui/saveload.cpp:157 +msgid "Delete" +msgstr "Suprimeix" + +#: gui/saveload.cpp:156 +msgid "Do you really want to delete this savegame?" +msgstr "Realment voleu suprimir aquesta partida?" + +#: gui/saveload.cpp:265 +msgid "Date: " +msgstr "Data: " + +#: gui/saveload.cpp:268 +msgid "Time: " +msgstr "Hora: " + +#: gui/saveload.cpp:273 +msgid "Playtime: " +msgstr "Temps de joc: " + +#: gui/saveload.cpp:286 gui/saveload.cpp:353 +msgid "Untitled savestate" +msgstr "Partida sense títol" + +#: gui/themebrowser.cpp:46 +msgid "Select a Theme" +msgstr "Seleccioneu un Tema" + +#: gui/ThemeEngine.cpp:337 +msgid "Disabled GFX" +msgstr "GFX desactivats" + +#: gui/ThemeEngine.cpp:338 +msgid "Standard Renderer (16bpp)" +msgstr "Pintat estàndard (16bpp)" + +#: gui/ThemeEngine.cpp:340 +msgid "Antialiased Renderer (16bpp)" +msgstr "Pintat amb antialias (16bpp)" + +#: base/main.cpp:205 +#, c-format +msgid "Engine does not support debug level '%s'" +msgstr "El motor no suporta el nivell de depuració '%s'" + +#: base/main.cpp:273 +msgid "Menu" +msgstr "Menú" + +#: base/main.cpp:276 backends/platform/symbian/src/SymbianActions.cpp:48 +#: backends/platform/wince/CEActionsPocket.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:45 +msgid "Skip" +msgstr "Salta" + +#: base/main.cpp:279 backends/platform/symbian/src/SymbianActions.cpp:53 +#: backends/platform/wince/CEActionsPocket.cpp:41 +msgid "Pause" +msgstr "Pausa" + +#: base/main.cpp:282 +msgid "Skip line" +msgstr "Salta la línia" + +#: base/main.cpp:404 +msgid "Error running game:" +msgstr "Error al executar el joc:" + +#: base/main.cpp:430 base/main.cpp:431 +msgid "Could not find any engine capable of running the selected game" +msgstr "No s'ha pogut trobar cap motor capaç d'executar el joc seleccionat" + +#: common/error.cpp:43 +msgid "Invalid Path" +msgstr "Camí incorrecte" + +#: common/error.cpp:44 +msgid "Game Data not found" +msgstr "No s'han trobat les dades del joc" + +#: common/error.cpp:45 +msgid "Game Id not supported" +msgstr "Identificador de joc no suportat" + +#: common/error.cpp:46 +msgid "Unsupported Color Mode" +msgstr "Mode de color no suportat" + +#: common/error.cpp:48 +msgid "Read permission denied" +msgstr "S'ha denegat el permís de lectura" + +#: common/error.cpp:49 +msgid "Write permission denied" +msgstr "S'ha denegat el permís d'escriptura" + +#: common/error.cpp:52 +msgid "Path not exists" +msgstr "El camí no existeix" + +#: common/error.cpp:53 +msgid "Path not a directory" +msgstr "El camí no és un directori" + +#: common/error.cpp:54 +msgid "Path not a file" +msgstr "El camí no és un fitxer" + +#: common/error.cpp:56 +msgid "Cannot create file" +msgstr "No s'ha pogut crear el fitxer" + +#: common/error.cpp:57 +msgid "Reading failed" +msgstr "Ha fallat la lectura" + +#: common/error.cpp:58 +msgid "Writing data failed" +msgstr "Ha fallat l'escriptura de dades" + +#: common/error.cpp:60 common/error.cpp:71 +msgid "Unknown Error" +msgstr "Error desconegut" + +#: common/util.cpp:254 +msgid "Hercules Green" +msgstr "Hercules Verd" + +#: common/util.cpp:255 +msgid "Hercules Amber" +msgstr "Hercules Àmbar" + +#: engines/dialogs.cpp:89 +msgid "~R~esume" +msgstr "~C~ontinua" + +#: engines/dialogs.cpp:91 +msgid "~L~oad" +msgstr "C~a~rrega" + +#: engines/dialogs.cpp:95 +msgid "~S~ave" +msgstr "~D~esa" + +#: engines/dialogs.cpp:99 +msgid "~O~ptions" +msgstr "~O~pcions" + +#: engines/dialogs.cpp:104 +msgid "~H~elp" +msgstr "~A~juda" + +#: engines/dialogs.cpp:107 +msgid "~A~bout" +msgstr "~Q~uant a" + +#: engines/dialogs.cpp:109 +msgid "~R~eturn to Launcher" +msgstr "~R~etorna al Llançador" + +#: engines/dialogs.cpp:119 +msgid "Save game:" +msgstr "Desa la partida:" + +#: engines/dialogs.cpp:119 backends/platform/symbian/src/SymbianActions.cpp:47 +#: backends/platform/wince/CEActionsPocket.cpp:42 +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Save" +msgstr "Desa" + +#: engines/dialogs.cpp:301 engines/mohawk/dialogs.cpp:84 +#: engines/mohawk/dialogs.cpp:118 +msgid "~O~K" +msgstr "~D~'acord" + +#: engines/dialogs.cpp:302 engines/mohawk/dialogs.cpp:85 +#: engines/mohawk/dialogs.cpp:119 +msgid "~C~ancel" +msgstr "~C~ancel·la" + +#: engines/dialogs.cpp:305 +msgid "~K~eys" +msgstr "~T~ecles" + +#: engines/scumm/dialogs.cpp:287 +msgid "~P~revious" +msgstr "~A~nterior" + +#: engines/scumm/dialogs.cpp:288 +msgid "~N~ext" +msgstr "~S~egüent" + +#: engines/scumm/dialogs.cpp:289 +#: backends/platform/ds/arm9/source/dsoptions.cpp:59 +msgid "~C~lose" +msgstr "~T~anca" + +#: engines/mohawk/dialogs.cpp:81 engines/mohawk/dialogs.cpp:115 +msgid "~Z~ip Mode Activated" +msgstr "Mode ~Z~ip activat" + +#: engines/mohawk/dialogs.cpp:82 +msgid "~T~ransitions Enabled" +msgstr "~T~ransicions activades" + +#: engines/mohawk/dialogs.cpp:116 +msgid "~W~ater Effect Enabled" +msgstr "~E~fecte de l'aigua activat" + +#: sound/fmopl.cpp:51 +msgid "MAME OPL emulator" +msgstr "Emulador OPL de MAME" + +#: sound/fmopl.cpp:53 +msgid "DOSBox OPL emulator" +msgstr "Emulador OPL de DOSBox" + +#: sound/null.h:45 +msgid "No music" +msgstr "Sense música" + +#: sound/softsynth/adlib.cpp:1590 +msgid "AdLib Emulator" +msgstr "Emulador d'AdLib" + +#: sound/softsynth/mt32.cpp:327 +msgid "Initialising MT-32 Emulator" +msgstr "Iniciant l'Emulador de MT-32" + +#: sound/softsynth/mt32.cpp:541 +msgid "MT-32 Emulator" +msgstr "Emulador de MT-32" + +#: sound/softsynth/pcspk.cpp:142 +msgid "PC Speaker Emulator" +msgstr "Emulador d'Altaveu de PC" + +#: sound/softsynth/pcspk.cpp:161 +msgid "IBM PCjr Emulator" +msgstr "Emulador d'IBM PCjr" + +#: sound/softsynth/ym2612.cpp:762 +msgid "FM Towns Emulator" +msgstr "Emulador de FM Towns" + +#: backends/keymapper/remap-dialog.cpp:49 +msgid "Keymap:" +msgstr "Mapa de teclat:" + +#: backends/keymapper/remap-dialog.cpp:66 +msgid " (Active)" +msgstr " (Actiu)" + +#: backends/keymapper/remap-dialog.cpp:100 +msgid " (Global)" +msgstr " (Global)" + +#: backends/keymapper/remap-dialog.cpp:110 +msgid " (Game)" +msgstr " (Joc)" + +#: backends/midi/windows.cpp:157 +msgid "Windows MIDI" +msgstr "MIDI de Windows" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:60 +msgid "ScummVM Main Menu" +msgstr "Menú Principal de ScummVM" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:66 +msgid "~L~eft handed mode" +msgstr "Mode ~e~squerrà" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:67 +msgid "~I~ndy fight controls" +msgstr "Controls de lluita de l'~I~ndy" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:68 +msgid "Show mouse cursor" +msgstr "Mostra el cursor del ratolí" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:69 +msgid "Snap to edges" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:71 +msgid "Touch X Offset" +msgstr "Desplaçament X del toc" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:78 +msgid "Touch Y Offset" +msgstr "Desplaçament Y del toc" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:90 +msgid "Use laptop trackpad-style cursor control" +msgstr "Utilitza el control del cursor a l'estil del trackpad dels portàtils" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:91 +msgid "Tap for left click, double tap right click" +msgstr "Toc per a clic esquerre, doble toc per a clic dret" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:93 +msgid "Sensitivity" +msgstr "Sensibilitat" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:102 +msgid "Initial top screen scale:" +msgstr "Escalat inicial de la pantalla superior:" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:108 +msgid "Main screen scaling:" +msgstr "Escalat de la pantalla principal:" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:110 +msgid "Hardware scale (fast, but low quality)" +msgstr "Escalat per hardware (ràpid, però de baixa qualitat)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:111 +msgid "Software scale (good quality, but slower)" +msgstr "Escalat per software (bona qualitat, però més lent)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:112 +msgid "Unscaled (you must scroll left and right)" +msgstr "Sense escalar (haureu de desplaçar-vos a esquerra i dreta)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:114 +msgid "Brightness:" +msgstr "Brillantor:" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:124 +msgid "High quality audio (slower) (reboot)" +msgstr "Alta qualitat d'àudio (més lent) (reiniciar)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:125 +msgid "Disable power off" +msgstr "Desactiva l'apagat automàtic" + +#: backends/platform/iphone/osys_events.cpp:339 +msgid "Touchpad mode enabled." +msgstr "Mode Touchpad activat." + +#: backends/platform/iphone/osys_events.cpp:341 +msgid "Touchpad mode disabled." +msgstr "Mode Touchpad desactivat." + +#: backends/platform/sdl/graphics.cpp:40 +#: backends/platform/wince/wince-sdl.cpp:111 +#: backends/platform/wince/wince-sdl.cpp:118 +msgid "Normal (no scaling)" +msgstr "Normal (sense escalar)" + +#: backends/platform/symbian/src/SymbianActions.cpp:41 +#: backends/platform/wince/CEActionsSmartphone.cpp:38 +msgid "Up" +msgstr "Amunt" + +#: backends/platform/symbian/src/SymbianActions.cpp:42 +#: backends/platform/wince/CEActionsSmartphone.cpp:39 +msgid "Down" +msgstr "Avall" + +#: backends/platform/symbian/src/SymbianActions.cpp:43 +#: backends/platform/wince/CEActionsSmartphone.cpp:40 +msgid "Left" +msgstr "Esquerra" + +#: backends/platform/symbian/src/SymbianActions.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:41 +msgid "Right" +msgstr "Dreta" + +#: backends/platform/symbian/src/SymbianActions.cpp:45 +#: backends/platform/wince/CEActionsPocket.cpp:59 +#: backends/platform/wince/CEActionsSmartphone.cpp:42 +msgid "Left Click" +msgstr "Clic esquerre" + +#: backends/platform/symbian/src/SymbianActions.cpp:46 +#: backends/platform/wince/CEActionsSmartphone.cpp:43 +msgid "Right Click" +msgstr "Clic dret" + +#: backends/platform/symbian/src/SymbianActions.cpp:49 +#: backends/platform/wince/CEActionsSmartphone.cpp:46 +msgid "Zone" +msgstr "Zona" + +#: backends/platform/symbian/src/SymbianActions.cpp:50 +#: backends/platform/wince/CEActionsPocket.cpp:53 +#: backends/platform/wince/CEActionsSmartphone.cpp:47 +msgid "Multi Function" +msgstr "Funció Múltiple" + +#: backends/platform/symbian/src/SymbianActions.cpp:51 +msgid "Swap character" +msgstr "Commuta el personatge" + +#: backends/platform/symbian/src/SymbianActions.cpp:52 +msgid "Skip text" +msgstr "Salta el text" + +#: backends/platform/symbian/src/SymbianActions.cpp:54 +msgid "Fast mode" +msgstr "Mode ràpid" + +#: backends/platform/symbian/src/SymbianActions.cpp:55 +#: backends/platform/wince/CEActionsPocket.cpp:43 +#: backends/platform/wince/CEActionsSmartphone.cpp:51 +msgid "Quit" +msgstr "Surt" + +#: backends/platform/symbian/src/SymbianActions.cpp:56 +msgid "Debugger" +msgstr "Depurador" + +#: backends/platform/symbian/src/SymbianActions.cpp:57 +msgid "Global menu" +msgstr "Menú global" + +#: backends/platform/symbian/src/SymbianActions.cpp:58 +msgid "Virtual keyboard" +msgstr "Teclat virtual" + +#: backends/platform/symbian/src/SymbianActions.cpp:59 +msgid "Key mapper" +msgstr "Mapejador de tecles" + +#: backends/platform/symbian/src/SymbianOS.cpp:446 +msgid "Do you want to quit ?" +msgstr "Vols sortir?" + +#: backends/platform/wii/options.cpp:51 +msgid "Video" +msgstr "Vídeo" + +#: backends/platform/wii/options.cpp:54 +msgid "Current video mode:" +msgstr "Mode de vídeo actual:" + +#: backends/platform/wii/options.cpp:56 +msgid "Double-strike" +msgstr "" + +#: backends/platform/wii/options.cpp:60 +msgid "Horizontal underscan:" +msgstr "" + +#: backends/platform/wii/options.cpp:66 +msgid "Vertical underscan:" +msgstr "" + +#: backends/platform/wii/options.cpp:71 +msgid "Input" +msgstr "Entrada" + +#: backends/platform/wii/options.cpp:74 +msgid "GC Pad sensitivity:" +msgstr "Sensibilitat del Pad GC:" + +#: backends/platform/wii/options.cpp:80 +msgid "GC Pad acceleration:" +msgstr "Acceleració del Pad GC:" + +#: backends/platform/wii/options.cpp:86 +msgid "DVD" +msgstr "DVD" + +#: backends/platform/wii/options.cpp:89 backends/platform/wii/options.cpp:101 +msgid "Status:" +msgstr "Estat:" + +#: backends/platform/wii/options.cpp:90 backends/platform/wii/options.cpp:102 +msgid "Unknown" +msgstr "Desconegut" + +#: backends/platform/wii/options.cpp:93 +msgid "Mount DVD" +msgstr "Munta el DVD" + +#: backends/platform/wii/options.cpp:94 +msgid "Unmount DVD" +msgstr "Desmunta el DVD" + +#: backends/platform/wii/options.cpp:98 +msgid "SMB" +msgstr "SMB" + +#: backends/platform/wii/options.cpp:106 +msgid "Server:" +msgstr "Servidor:" + +#: backends/platform/wii/options.cpp:110 +msgid "Share:" +msgstr "Compartició:" + +#: backends/platform/wii/options.cpp:114 +msgid "Username:" +msgstr "Nom d'usuari:" + +#: backends/platform/wii/options.cpp:118 +msgid "Password:" +msgstr "Contrasenya:" + +#: backends/platform/wii/options.cpp:121 +msgid "Init network" +msgstr "Inicia la xarxa" + +#: backends/platform/wii/options.cpp:123 +msgid "Mount SMB" +msgstr "Munta SMB" + +#: backends/platform/wii/options.cpp:124 +msgid "Unmount SMB" +msgstr "Desmunta SMB" + +#: backends/platform/wii/options.cpp:145 +msgid "DVD Mounted successfully" +msgstr "El DVD s'ha muntat satisfactòriament" + +#: backends/platform/wii/options.cpp:148 +msgid "Error while mounting the DVD" +msgstr "Error al muntar el DVD" + +#: backends/platform/wii/options.cpp:150 +msgid "DVD not mounted" +msgstr "El DVD no està muntat" + +#: backends/platform/wii/options.cpp:163 +msgid "Network up, share mounted" +msgstr "Xarxa activa, compartició muntada" + +#: backends/platform/wii/options.cpp:165 +msgid "Network up" +msgstr "Xarxa activa" + +#: backends/platform/wii/options.cpp:168 +msgid ", error while mounting the share" +msgstr ", error al muntar la compartició" + +#: backends/platform/wii/options.cpp:170 +msgid ", share not mounted" +msgstr ", compartició no muntada" + +#: backends/platform/wii/options.cpp:176 +msgid "Network down" +msgstr "Xarxa inactiva" + +#: backends/platform/wii/options.cpp:180 +msgid "Initialising network" +msgstr "Iniciant la xarxa" + +#: backends/platform/wii/options.cpp:184 +msgid "Timeout while initialising network" +msgstr "" + +#: backends/platform/wii/options.cpp:188 +#, c-format +msgid "Network not initialsed (%d)" +msgstr "Xarxa no iniciada (%d)" + +#: backends/platform/wince/CEActionsPocket.cpp:45 +msgid "Hide Toolbar" +msgstr "Oculta la barra d'eines" + +#: backends/platform/wince/CEActionsPocket.cpp:46 +msgid "Show Keyboard" +msgstr "Mostra el teclat" + +#: backends/platform/wince/CEActionsPocket.cpp:47 +msgid "Sound on/off" +msgstr "So engegat/parat" + +#: backends/platform/wince/CEActionsPocket.cpp:48 +msgid "Right click" +msgstr "Clic dret" + +#: backends/platform/wince/CEActionsPocket.cpp:49 +msgid "Show/Hide Cursor" +msgstr "Mostra/Oculta el cursor" + +#: backends/platform/wince/CEActionsPocket.cpp:50 +msgid "Free look" +msgstr "Vista lliure" + +#: backends/platform/wince/CEActionsPocket.cpp:51 +msgid "Zoom up" +msgstr "Amplia" + +#: backends/platform/wince/CEActionsPocket.cpp:52 +msgid "Zoom down" +msgstr "Redueix" + +#: backends/platform/wince/CEActionsPocket.cpp:54 +#: backends/platform/wince/CEActionsSmartphone.cpp:48 +msgid "Bind Keys" +msgstr "Mapeja tecles" + +#: backends/platform/wince/CEActionsPocket.cpp:55 +msgid "Cursor Up" +msgstr "Cursor Amunt" + +#: backends/platform/wince/CEActionsPocket.cpp:56 +msgid "Cursor Down" +msgstr "Cursor Avall" + +#: backends/platform/wince/CEActionsPocket.cpp:57 +msgid "Cursor Left" +msgstr "Cursor Esquerra" + +#: backends/platform/wince/CEActionsPocket.cpp:58 +msgid "Cursor Right" +msgstr "Cursor Dreta" + +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Do you want to load or save the game?" +msgstr "Voleu carregar o desar el joc?" + +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +msgid " Are you sure you want to quit ? " +msgstr "" + +#: backends/platform/wince/CEActionsSmartphone.cpp:49 +msgid "Keyboard" +msgstr "Teclat" + +#: backends/platform/wince/CEActionsSmartphone.cpp:50 +msgid "Rotate" +msgstr "Rotar" + +#: backends/platform/wince/CELauncherDialog.cpp:58 +msgid "Using SDL driver " +msgstr "Utilitzant el controlador SDL " + +#: backends/platform/wince/CELauncherDialog.cpp:62 +msgid "Display " +msgstr "Pantalla" + +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "Do you want to perform an automatic scan ?" +msgstr "Voleu fer una cerca automàtica?" + +#~ msgid "Failed to load any GUI theme, aborting" +#~ msgstr "No s'ha pogut carregar cap tema de la interfície d'usuari, avortant" + +#, fuzzy +#~ msgid "User picked target '%s' (gameid '%s')...\n" +#~ msgstr "" +#~ "L'usuari ha seleccionat el target '%s' (identificador de joc '%s')...\n" + +#~ msgid " Looking for a plugin supporting this gameid... " +#~ msgstr " Cercant un connector que suporti aquest identificador de joc... " + +#~ msgid "failed\n" +#~ msgstr "ha fallat\n" + +#~ msgid "" +#~ "%s is an invalid gameid. Use the --list-games option to list supported " +#~ "gameid" +#~ msgstr "" +#~ "%s és un identificador de joc invàlid. Utilitzeu l'opció --list-games per " +#~ "llistar els identificadors de joc suportats" + +#~ msgid " Starting '%s'\n" +#~ msgstr " Iniciant '%s'\n" + +#, fuzzy +#~ msgid "%s failed to instantiate engine: %s (target '%s', path '%s')" +#~ msgstr "%s ha fallat l'iniciat del motor: %s (target '%s', camí '%s')" + +#~ msgid "Chinese (Taiwan)" +#~ msgstr "Xinès (Taiwan)" + +#~ msgid "Czech" +#~ msgstr "Txec" + +#~ msgid "Dutch" +#~ msgstr "Danès" + +#~ msgid "English (GB)" +#~ msgstr "Anglès (GB)" + +#~ msgid "English (US)" +#~ msgstr "Anglès (EUA)" + +#~ msgid "French" +#~ msgstr "Francès" + +#~ msgid "German" +#~ msgstr "Alemany" + +#~ msgid "Hebrew" +#~ msgstr "Hebreu" + +#~ msgid "Italian" +#~ msgstr "Italià" + +#~ msgid "Japanese" +#~ msgstr "Japonès" + +#~ msgid "Korean" +#~ msgstr "Coreà" + +#~ msgid "Polish" +#~ msgstr "Polac" + +#~ msgid "Portuguese" +#~ msgstr "Portuguès" + +#~ msgid "Russian" +#~ msgstr "Rus" + +#~ msgid "Spanish" +#~ msgstr "Espanyol" + +#~ msgid "Swedish" +#~ msgstr "Suís" + +#~ msgid "Failed to load MT32_CONTROL.ROM" +#~ msgstr "No s'ha pogut carregar el fitxer MT32_CONTROL.ROM" + +#~ msgid "Failed to load MT32_PCM.ROM" +#~ msgstr "No s'ha pogut carregar el fitxer MT32_PCM.ROM" diff --git a/po/de_DE.po b/po/de_DE.po new file mode 100644 index 0000000000..4b3f493a03 --- /dev/null +++ b/po/de_DE.po @@ -0,0 +1,1442 @@ +# LANGUAGE translation for ScummVM. +# Copyright (C) 2010 ScummVM Team +# This file is distributed under the same license as the ScummVM package. +# FIRST AUTHOR <EMAIL@ADDRESS>, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: ScummVM 1.2.0svn\n" +"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n" +"POT-Creation-Date: 2010-07-12 17:44+0200\n" +"PO-Revision-Date: 2010-07-09 20:37+0100\n" +"Last-Translator: Simon Sawatzki\n" +"Language-Team: Lothar Serra Mari <Lothar@Windowsbase.de> & Simon Sawatzki " +"<SimSaw@gmx.de>\n" +"Language: Deutsch\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#: gui/about.cpp:96 +#, c-format +msgid "(built on %s)" +msgstr "(erstellt am %s)" + +#: gui/about.cpp:103 +msgid "Features compiled in:" +msgstr "Verwendete Funktionen:" + +#: gui/about.cpp:112 +msgid "Available engines:" +msgstr "Verfügbare Spiele-Engines:" + +#: gui/browser.cpp:69 +msgid "Go up" +msgstr "Pfad hoch" + +#: gui/browser.cpp:69 +msgid "Go to previous directory level" +msgstr "Zu höherer Pfadebene wechseln" + +#: gui/browser.cpp:70 gui/chooser.cpp:49 gui/KeysDialog.cpp:46 +#: gui/launcher.cpp:266 gui/massadd.cpp:95 gui/options.cpp:972 +#: gui/saveload.cpp:65 gui/saveload.cpp:157 gui/themebrowser.cpp:56 +#: backends/platform/wii/options.cpp:48 +msgid "Cancel" +msgstr "Abbrechen" + +#: gui/browser.cpp:71 gui/chooser.cpp:50 gui/themebrowser.cpp:57 +msgid "Choose" +msgstr "Auswählen" + +#: gui/GuiManager.cpp:102 backends/keymapper/remap-dialog.cpp:54 +msgid "Close" +msgstr "Schließen" + +#: gui/GuiManager.cpp:105 +msgid "Mouse click" +msgstr "Mausklick" + +#: gui/GuiManager.cpp:108 base/main.cpp:285 +msgid "Display keyboard" +msgstr "Tastatur anzeigen" + +#: gui/GuiManager.cpp:111 base/main.cpp:288 +msgid "Remap keys" +msgstr "Tasten neu zuweisen" + +#: gui/KeysDialog.cpp:44 +msgid "Map" +msgstr "Zuweisen" + +#: gui/KeysDialog.cpp:45 gui/launcher.cpp:267 gui/launcher.cpp:873 +#: gui/launcher.cpp:877 gui/massadd.cpp:92 gui/options.cpp:973 +#: backends/platform/wii/options.cpp:47 +#: backends/platform/wince/CELauncherDialog.cpp:56 +msgid "OK" +msgstr "OK" + +#: gui/KeysDialog.cpp:52 +msgid "Select an action and click 'Map'" +msgstr "Aktion auswählen und \"Zuweisen\" klicken" + +#: gui/KeysDialog.cpp:83 gui/KeysDialog.cpp:105 gui/KeysDialog.cpp:144 +#, c-format +msgid "Associated key : %s" +msgstr "Zugewiesene Taste: %s" + +#: gui/KeysDialog.cpp:85 gui/KeysDialog.cpp:107 gui/KeysDialog.cpp:146 +#, c-format +msgid "Associated key : none" +msgstr "Zugewiesene Taste: keine" + +#: gui/KeysDialog.cpp:93 +msgid "Please select an action" +msgstr "Bitte eine Aktion auswählen" + +#: gui/KeysDialog.cpp:109 +msgid "Press the key to associate" +msgstr "Taste drücken, um sie zuzuweisen" + +#: gui/KeysDialog.cpp:148 +msgid "Choose an action to map" +msgstr "Eine Aktion zum Zuweisen auswählen" + +#: gui/launcher.cpp:170 +msgid "Game" +msgstr "Spiel" + +#: gui/launcher.cpp:173 +msgid "ID:" +msgstr "Kennung:" + +#: gui/launcher.cpp:173 gui/launcher.cpp:174 +msgid "" +"Short game identifier used for referring to savegames and running the game " +"from the command line" +msgstr "" +"Kurzer Spielname, um die Spielstände zuzuordnen und das Spiel von der " +"Kommandozeile aus starten zu können" + +#: gui/launcher.cpp:177 +msgid "Name:" +msgstr "Name:" + +#: gui/launcher.cpp:177 gui/launcher.cpp:178 +msgid "Full title of the game" +msgstr "Voller Name des Spiels" + +#: gui/launcher.cpp:181 +msgid "Language:" +msgstr "Sprache:" + +#: gui/launcher.cpp:181 gui/launcher.cpp:182 +msgid "" +"Language of the game. This will not turn your Spanish game version into " +"English" +msgstr "" +"Sprache des Spiels. Diese Funktion wird nicht eine spanische Version des " +"Spiels in eine deutsche verwandeln." + +#: gui/launcher.cpp:183 gui/launcher.cpp:194 gui/options.cpp:80 +#: gui/options.cpp:617 gui/options.cpp:627 gui/options.cpp:943 +#: sound/null.cpp:42 +msgid "<default>" +msgstr "<Standard>" + +#: gui/launcher.cpp:192 +msgid "Platform:" +msgstr "Plattform:" + +#: gui/launcher.cpp:192 gui/launcher.cpp:193 +msgid "Platform the game was originally designed for" +msgstr "Plattform, für die das Spiel ursprünglich erstellt wurde" + +#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867 +msgid "Graphics" +msgstr "Grafik" + +#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867 +msgid "GFX" +msgstr "GFX" + +#: gui/launcher.cpp:206 +msgid "Override global graphic settings" +msgstr "Globale Grafikeinstellungen übergehen" + +#: gui/launcher.cpp:213 gui/options.cpp:873 +msgid "Audio" +msgstr "Audio" + +#: gui/launcher.cpp:215 +msgid "Override global audio settings" +msgstr "Globale Audioeinstellungen übergehen" + +#: gui/launcher.cpp:223 gui/options.cpp:877 +msgid "Volume" +msgstr "Lautstärke" + +#: gui/launcher.cpp:225 +msgid "Override global volume settings" +msgstr "Globale Lautstärke-Einstellungen übergehen" + +#: gui/launcher.cpp:232 gui/options.cpp:885 +msgid "MIDI" +msgstr "MIDI" + +#: gui/launcher.cpp:234 +msgid "Override global MIDI settings" +msgstr "Globale MIDI-Einstellungen übergehen" + +#: gui/launcher.cpp:244 gui/options.cpp:891 +msgid "Paths" +msgstr "Pfade" + +#: gui/launcher.cpp:250 +msgid "Game Path:" +msgstr "Spielpfad:" + +#: gui/launcher.cpp:254 gui/options.cpp:904 +msgid "Extra Path:" +msgstr "Extrapfad:" + +#: gui/launcher.cpp:254 gui/launcher.cpp:255 +msgid "Specifies path to additional data used the game" +msgstr "Legt das Verzeichnis für zusätzliche Spieldateien fest." + +#: gui/launcher.cpp:258 +msgid "Save Path:" +msgstr "Spielstände:" + +#: gui/launcher.cpp:258 gui/launcher.cpp:259 gui/options.cpp:898 +#: gui/options.cpp:899 +msgid "Specifies where your savegames are put" +msgstr "Legt fest, wo die Spielstände abgelegt werden." + +#: gui/launcher.cpp:275 gui/launcher.cpp:353 gui/launcher.cpp:398 +#: gui/options.cpp:245 gui/options.cpp:400 gui/options.cpp:486 +#: gui/options.cpp:545 gui/options.cpp:706 gui/options.cpp:902 +#: gui/options.cpp:905 gui/options.cpp:909 gui/options.cpp:996 +#: gui/options.cpp:1002 gui/options.cpp:1008 gui/options.cpp:1016 +#: gui/options.cpp:1040 gui/options.cpp:1044 gui/options.cpp:1050 +#: gui/options.cpp:1057 gui/options.cpp:1156 +msgid "None" +msgstr "-" + +#: gui/launcher.cpp:280 gui/launcher.cpp:357 +#: backends/platform/wii/options.cpp:56 +msgid "Default" +msgstr "Standard" + +#: gui/launcher.cpp:391 gui/options.cpp:1150 +msgid "Select SoundFont" +msgstr "SoundFont auswählen" + +#: gui/launcher.cpp:410 gui/launcher.cpp:548 +msgid "Select directory with game data" +msgstr "Verzeichnis mit Spieldateien auswählen" + +#: gui/launcher.cpp:428 +msgid "Select additional game directory" +msgstr "Verzeichnis mit zusätzlichen Dateien auswählen" + +#: gui/launcher.cpp:440 +msgid "Select directory for saved games" +msgstr "Verzeichnis für Spielstände auswählen" + +#: gui/launcher.cpp:459 +msgid "This game ID is already taken. Please choose another one." +msgstr "Diese Spielkennung ist schon vergeben. Bitte eine andere wählen." + +#: gui/launcher.cpp:500 engines/dialogs.cpp:113 +msgid "~Q~uit" +msgstr "~B~eenden" + +#: gui/launcher.cpp:500 +msgid "Quit ScummVM" +msgstr "ScummVM beenden" + +#: gui/launcher.cpp:501 +msgid "A~b~out..." +msgstr "Übe~r~" + +#: gui/launcher.cpp:501 +msgid "About ScummVM" +msgstr "Über ScummVM" + +#: gui/launcher.cpp:502 +msgid "~O~ptions..." +msgstr "~O~ptionen" + +#: gui/launcher.cpp:502 +msgid "Change global ScummVM options" +msgstr "Globale ScummVM-Einstellungen bearbeiten" + +#: gui/launcher.cpp:504 +msgid "~S~tart" +msgstr "~S~tarten" + +#: gui/launcher.cpp:504 +msgid "Start selected game" +msgstr "Ausgewähltes Spiel starten" + +#: gui/launcher.cpp:507 +msgid "~L~oad..." +msgstr "~L~aden..." + +#: gui/launcher.cpp:507 +msgid "Load savegame for selected game" +msgstr "Spielstand für ausgewähltes Spiel laden" + +#: gui/launcher.cpp:511 +msgid "~A~dd Game..." +msgstr "Spiel ~h~inzufügen" + +#: gui/launcher.cpp:511 +msgid "Hold Shift for Mass Add" +msgstr "" +"Umschalttaste (Shift) gedrückt halten, um Verzeichnisse nach Spielen zu " +"durchsuchen" + +#: gui/launcher.cpp:513 +msgid "~E~dit Game..." +msgstr "Spielo~p~tionen" + +#: gui/launcher.cpp:513 +msgid "Change game options" +msgstr "Spieloptionen ändern" + +#: gui/launcher.cpp:515 +msgid "~R~emove Game" +msgstr "Spiel ~e~ntfernen" + +#: gui/launcher.cpp:515 +msgid "Remove game from the list. The game data files stay intact" +msgstr "Spiel aus der Liste entfernen. Die Spieldateien bleiben erhalten." + +#: gui/launcher.cpp:522 +msgid "Search in game list" +msgstr "In Spieleliste suchen" + +#: gui/launcher.cpp:526 gui/launcher.cpp:1037 +msgid "Search:" +msgstr "Suchen:" + +#: gui/launcher.cpp:529 gui/options.cpp:707 +msgid "Clear value" +msgstr "Wert löschen" + +#: gui/launcher.cpp:551 engines/dialogs.cpp:117 +msgid "Load game:" +msgstr "Spiel laden:" + +#: gui/launcher.cpp:551 engines/dialogs.cpp:117 +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Load" +msgstr "Laden" + +#: gui/launcher.cpp:660 +msgid "" +"Do you really want to run the mass game detector? This could potentially add " +"a huge number of games." +msgstr "" +"Möchten Sie wirklich den PC nach Spielen durchsuchen? Möglicherweise wird " +"dabei eine größere Menge an Spielen hinzugefügt." + +#: gui/launcher.cpp:661 gui/launcher.cpp:810 +#: backends/platform/symbian/src/SymbianOS.cpp:446 +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "Yes" +msgstr "Ja" + +#: gui/launcher.cpp:661 gui/launcher.cpp:810 +#: backends/platform/symbian/src/SymbianOS.cpp:446 +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "No" +msgstr "Nein" + +#: gui/launcher.cpp:708 +msgid "ScummVM couldn't open the specified directory!" +msgstr "ScummVM kann das gewählte Verzeichnis nicht öffnen!" + +#: gui/launcher.cpp:720 +msgid "ScummVM could not find any game in the specified directory!" +msgstr "ScummVM kann in dem gewählten Verzeichnis kein Spiel finden!" + +#: gui/launcher.cpp:734 +msgid "Pick the game:" +msgstr "Spiel auswählen:" + +#: gui/launcher.cpp:810 +msgid "Do you really want to remove this game configuration?" +msgstr "Möchten Sie wirklich diese Spielkonfiguration entfernen?" + +#: gui/launcher.cpp:873 +msgid "This game does not support loading games from the launcher." +msgstr "" +"Für dieses Spiel wird das Laden aus der Spieleliste heraus nicht unterstützt." + +#: gui/launcher.cpp:877 +msgid "ScummVM could not find any engine capable of running the selected game!" +msgstr "ScummVM konnte keine Engine finden, um das Spiel zu starten!" + +#: gui/launcher.cpp:989 +msgid "Mass Add..." +msgstr "Durchsuchen" + +#: gui/launcher.cpp:990 +msgid "Add Game..." +msgstr "Spiel hinzufügen" + +#: gui/massadd.cpp:79 gui/massadd.cpp:82 +msgid "... progress ..." +msgstr "... läuft..." + +#: gui/massadd.cpp:244 +msgid "Scan complete!" +msgstr "Suchlauf abgeschlossen!" + +#: gui/massadd.cpp:247 +#, c-format +msgid "Discovered %d new games." +msgstr "%d neue Spiele gefunden." + +#: gui/massadd.cpp:251 +#, c-format +msgid "Scanned %d directories ..." +msgstr "%d Ordner durchsucht..." + +#: gui/massadd.cpp:254 +#, c-format +msgid "Discovered %d new games ..." +msgstr "%d neue Spiele gefunden..." + +#: gui/options.cpp:78 +msgid "Never" +msgstr "Niemals" + +#: gui/options.cpp:78 +msgid "every 5 mins" +msgstr "alle 5 Minuten" + +#: gui/options.cpp:78 +msgid "every 10 mins" +msgstr "alle 10 Minuten" + +#: gui/options.cpp:78 +msgid "every 15 mins" +msgstr "alle 15 Minuten" + +#: gui/options.cpp:78 +msgid "every 30 mins" +msgstr "alle 30 Minuten" + +#: gui/options.cpp:80 +msgid "8 kHz" +msgstr "8 kHz" + +#: gui/options.cpp:80 +msgid "11kHz" +msgstr "11 kHz" + +#: gui/options.cpp:80 +msgid "22 kHz" +msgstr "22 kHz" + +#: gui/options.cpp:80 +msgid "44 kHz" +msgstr "44 kHz" + +#: gui/options.cpp:80 +msgid "48 kHz" +msgstr "48 kHz" + +#: gui/options.cpp:614 +msgid "Graphics mode:" +msgstr "Grafikmodus:" + +#: gui/options.cpp:625 +msgid "Render mode:" +msgstr "Render-Modus:" + +#: gui/options.cpp:625 gui/options.cpp:626 +msgid "Special dithering modes supported by some games" +msgstr "" +"Spezielle Farbmischungsmethoden werden von manchen Spielen unterstützt." + +#: gui/options.cpp:635 +msgid "Fullscreen mode" +msgstr "Vollbildmodus" + +#: gui/options.cpp:638 +msgid "Aspect ratio correction" +msgstr "Seitenverhältnis korrigieren" + +#: gui/options.cpp:638 +msgid "Correct aspect ratio for 320x200 games" +msgstr "Seitenverhältnis für Spiele mit der Auflösung 320x200 korrigieren" + +#: gui/options.cpp:645 +msgid "Preferred Device:" +msgstr "Standard-Gerät:" + +#: gui/options.cpp:645 +msgid "Music Device:" +msgstr "Musikgerät:" + +#: gui/options.cpp:645 +msgid "Specifies preferred sound device or sound card emulator" +msgstr "" +"Legt das bevorzugte Tonwiedergabe-Gerät oder den Soundkarten-Emulator fest." + +#: gui/options.cpp:645 gui/options.cpp:646 +msgid "Specifies output sound device or sound card emulator" +msgstr "Legt das Musikwiedergabe-Gerät oder den Soundkarten-Emulator fest." + +#: gui/options.cpp:648 +#, fuzzy +msgid "MT-32 Device:" +msgstr "MT32-Gerät:" + +#: gui/options.cpp:648 +msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output" +msgstr "" +"Legt das standardmäßige Tonwiedergabe-Gerät für die Ausgabe von Roland MT-32/" +"LAPC1/CM32l/CM64 fest." + +#: gui/options.cpp:650 +msgid "GM Device:" +msgstr "GM-Gerät:" + +#: gui/options.cpp:650 +msgid "Specifies default sound device for General MIDI output" +msgstr "" +"Legt das standardmäßige Musikwiedergabe-Gerät für General-MIDI-Ausgabe fest." + +#: gui/options.cpp:682 +msgid "AdLib emulator:" +msgstr "AdLib-Emulator" + +#: gui/options.cpp:682 gui/options.cpp:683 +msgid "AdLib is used for music in many games" +msgstr "AdLib wird für die Musik in vielen Spielen verwendet." + +#: gui/options.cpp:693 +msgid "Output rate:" +msgstr "Ausgabefrequenz:" + +#: gui/options.cpp:693 gui/options.cpp:694 +msgid "" +"Higher value specifies better sound quality but may be not supported by your " +"soundcard" +msgstr "" +"Höhere Werte bewirken eine bessere Soundqualität, werden aber möglicherweise " +"nicht von jeder Soundkarte unterstützt." + +#: gui/options.cpp:705 +msgid "SoundFont:" +msgstr "SoundFont:" + +#: gui/options.cpp:705 gui/options.cpp:706 +msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity" +msgstr "" +"SoundFont wird von einigen Soundkarten, Fluidsynth und Timidity unterstützt." + +#: gui/options.cpp:710 +msgid "Mixed AdLib/MIDI mode" +msgstr "AdLib-/MIDI-Modus" + +#: gui/options.cpp:710 +msgid "Use both MIDI and AdLib sound generation" +msgstr "Benutzt MIDI und AdLib zur Sounderzeugung." + +#: gui/options.cpp:713 +msgid "True Roland MT-32 (disable GM emulation)" +msgstr "Echte Roland-MT-32-Emulation (GM-Emulation deaktiviert)" + +#: gui/options.cpp:713 +msgid "" +"Check if you want to use your real hardware Roland-compatible sound device " +"connected to your computer" +msgstr "" +"Wählen Sie dies aus, wenn Sie Ihre echte Hardware, die mit einer Roland-" +"kompatiblen Soundkarte verbunden ist, verwenden möchten." + +#: gui/options.cpp:716 +msgid "Enable Roland GS Mode" +msgstr "Roland-GS-Modus" + +#: gui/options.cpp:716 +msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack" +msgstr "" +"Schaltet die General-MIDI-Zuweisung für Spiele mit Roland-MT-32-Audiospur " +"aus." + +#: gui/options.cpp:719 +msgid "MIDI gain:" +msgstr "MIDI-Lautstärke:" + +#: gui/options.cpp:732 +msgid "Text and Speech:" +msgstr "Text und Sprache:" + +#: gui/options.cpp:737 gui/options.cpp:743 +msgid "Speech" +msgstr "Sprache" + +#: gui/options.cpp:738 gui/options.cpp:744 +msgid "Subtitles" +msgstr "Untertitel" + +#: gui/options.cpp:739 gui/options.cpp:745 +msgid "Both" +msgstr "Beides" + +#: gui/options.cpp:743 +msgid "Spch" +msgstr "Spr." + +#: gui/options.cpp:744 +msgid "Subs" +msgstr "Untert." + +#: gui/options.cpp:745 +msgid "Show subtitles and play speech" +msgstr "Untertitel anzeigen und Sprachausgabe aktivieren" + +#: gui/options.cpp:749 +msgid "Subtitle speed:" +msgstr "Untertitel-Tempo:" + +#: gui/options.cpp:761 +msgid "Music volume:" +msgstr "Musiklautstärke:" + +#: gui/options.cpp:768 +msgid "Mute All" +msgstr "Alles aus" + +#: gui/options.cpp:771 +msgid "SFX volume:" +msgstr "Effektlautstärke:" + +#: gui/options.cpp:771 gui/options.cpp:772 +msgid "Special sound effects volume" +msgstr "Lautstärke spezieller Soundeffekte" + +#: gui/options.cpp:778 +msgid "Speech volume:" +msgstr "Sprachlautstärke:" + +#: gui/options.cpp:898 +msgid "Save Path: " +msgstr "Spielstände: " + +#: gui/options.cpp:901 +msgid "Theme Path:" +msgstr "Themenpfad:" + +#: gui/options.cpp:904 gui/options.cpp:905 +msgid "Specifies path to additional data used by all games or ScummVM" +msgstr "" +"Legt das Verzeichnis für zusätzliche Spieldateien für alle Spiele in ScummVM " +"fest." + +#: gui/options.cpp:908 +msgid "Plugins Path:" +msgstr "Plugin-Pfad:" + +#: gui/options.cpp:913 +msgid "Misc" +msgstr "Sonstiges" + +#: gui/options.cpp:915 +msgid "Theme:" +msgstr "Thema:" + +#: gui/options.cpp:919 +msgid "GUI Renderer:" +msgstr "GUI-Renderer:" + +#: gui/options.cpp:925 +msgid "Autosave:" +msgstr "Autom. Speichern:" + +#: gui/options.cpp:933 +msgid "Keys" +msgstr "Tasten" + +#: gui/options.cpp:940 +msgid "GUI Language:" +msgstr "GUI-Sprache:" + +#: gui/options.cpp:940 +msgid "Language of ScummVM GUI" +msgstr "Sprache der ScummVM-Oberfläche" + +#: gui/options.cpp:945 +msgid "English" +msgstr "English" + +#: gui/options.cpp:1089 +msgid "You have to restart ScummVM to take the effect." +msgstr "Sie müssen ScummVM neustarten, um die Einstellungen zu übernehmen." + +#: gui/options.cpp:1102 +msgid "Select directory for savegames" +msgstr "Verzeichnis für Spielstände auswählen" + +#: gui/options.cpp:1109 +msgid "The chosen directory cannot be written to. Please select another one." +msgstr "" +"In das gewählte Verzeichnis kann nicht geschrieben werden. Bitte ein anderes " +"auswählen." + +#: gui/options.cpp:1118 +msgid "Select directory for GUI themes" +msgstr "Verzeichnis für Oberflächen-Themen" + +#: gui/options.cpp:1128 +msgid "Select directory for extra files" +msgstr "Verzeichnis für zusätzliche Dateien auswählen" + +#: gui/options.cpp:1139 +msgid "Select directory for plugins" +msgstr "Verzeichnis für Erweiterungen auswählen" + +#: gui/saveload.cpp:60 gui/saveload.cpp:241 +msgid "No date saved" +msgstr "Kein Datum gespeichert" + +#: gui/saveload.cpp:61 gui/saveload.cpp:242 +msgid "No time saved" +msgstr "Keine Zeit gespeichert" + +#: gui/saveload.cpp:62 gui/saveload.cpp:243 +msgid "No playtime saved" +msgstr "Keine Spielzeit gespeichert" + +#: gui/saveload.cpp:69 gui/saveload.cpp:157 +msgid "Delete" +msgstr "Löschen" + +#: gui/saveload.cpp:156 +msgid "Do you really want to delete this savegame?" +msgstr "Diesen Spielstand wirklich löschen?" + +#: gui/saveload.cpp:265 +msgid "Date: " +msgstr "Datum: " + +#: gui/saveload.cpp:268 +msgid "Time: " +msgstr "Zeit: " + +#: gui/saveload.cpp:273 +msgid "Playtime: " +msgstr "Spieldauer: " + +#: gui/saveload.cpp:286 gui/saveload.cpp:353 +msgid "Untitled savestate" +msgstr "Unbenannt" + +#: gui/themebrowser.cpp:46 +msgid "Select a Theme" +msgstr "Thema auswählen" + +#: gui/ThemeEngine.cpp:337 +msgid "Disabled GFX" +msgstr "GFX ausgeschalten" + +#: gui/ThemeEngine.cpp:338 +msgid "Standard Renderer (16bpp)" +msgstr "Standard-Renderer (16bpp)" + +#: gui/ThemeEngine.cpp:340 +msgid "Antialiased Renderer (16bpp)" +msgstr "Kantenglättung (16bpp)" + +#: base/main.cpp:205 +#, c-format +msgid "Engine does not support debug level '%s'" +msgstr "Engine unterstützt den Debug-Level \"%s\" nicht" + +#: base/main.cpp:273 +msgid "Menu" +msgstr "Menü" + +#: base/main.cpp:276 backends/platform/symbian/src/SymbianActions.cpp:48 +#: backends/platform/wince/CEActionsPocket.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:45 +msgid "Skip" +msgstr "Überspringen" + +#: base/main.cpp:279 backends/platform/symbian/src/SymbianActions.cpp:53 +#: backends/platform/wince/CEActionsPocket.cpp:41 +msgid "Pause" +msgstr "Pause" + +#: base/main.cpp:282 +msgid "Skip line" +msgstr "Zeile überspringen" + +#: base/main.cpp:404 +msgid "Error running game:" +msgstr "Fehler beim Ausführen des Spiels:" + +#: base/main.cpp:430 base/main.cpp:431 +msgid "Could not find any engine capable of running the selected game" +msgstr "Kann keine Spiel-Engine finden, die dieses Spiel starten kann." + +#: common/error.cpp:43 +msgid "Invalid Path" +msgstr "Ungültiges Verzeichnis" + +#: common/error.cpp:44 +msgid "Game Data not found" +msgstr "Spieldaten nicht gefunden" + +#: common/error.cpp:45 +msgid "Game Id not supported" +msgstr "Spielkennung nicht unterstützt" + +#: common/error.cpp:46 +msgid "Unsupported Color Mode" +msgstr "Farbmodus nicht unterstützt" + +#: common/error.cpp:48 +msgid "Read permission denied" +msgstr "Lese-Berechtigung nicht vorhanden" + +#: common/error.cpp:49 +msgid "Write permission denied" +msgstr "Schreib-Berechtigung nicht vorhanden" + +#: common/error.cpp:52 +msgid "Path not exists" +msgstr "Verzeichnis existiert nicht." + +#: common/error.cpp:53 +msgid "Path not a directory" +msgstr "Ungültiges Verzeichnis" + +#: common/error.cpp:54 +msgid "Path not a file" +msgstr "Pfad ist keine Datei." + +#: common/error.cpp:56 +msgid "Cannot create file" +msgstr "Kann Datei nicht erstellen." + +#: common/error.cpp:57 +msgid "Reading failed" +msgstr "Lesefehler aufgetreten" + +#: common/error.cpp:58 +msgid "Writing data failed" +msgstr "Daten konnten nicht geschrieben werden." + +#: common/error.cpp:60 common/error.cpp:71 +msgid "Unknown Error" +msgstr "Unbekannter Fehler" + +#: common/util.cpp:254 +msgid "Hercules Green" +msgstr "Hercules-Grün" + +#: common/util.cpp:255 +msgid "Hercules Amber" +msgstr "Hercules Bernsteingelb" + +#: engines/dialogs.cpp:89 +msgid "~R~esume" +msgstr "~F~ortsetzen" + +#: engines/dialogs.cpp:91 +msgid "~L~oad" +msgstr "~L~aden" + +#: engines/dialogs.cpp:95 +msgid "~S~ave" +msgstr "~S~peichern" + +#: engines/dialogs.cpp:99 +msgid "~O~ptions" +msgstr "~O~ptionen" + +#: engines/dialogs.cpp:104 +msgid "~H~elp" +msgstr "~H~ilfe" + +#: engines/dialogs.cpp:107 +msgid "~A~bout" +msgstr "Übe~r~" + +#: engines/dialogs.cpp:109 +msgid "~R~eturn to Launcher" +msgstr "Zur Spiele~l~iste zurück" + +#: engines/dialogs.cpp:119 +msgid "Save game:" +msgstr "Speichern:" + +#: engines/dialogs.cpp:119 backends/platform/symbian/src/SymbianActions.cpp:47 +#: backends/platform/wince/CEActionsPocket.cpp:42 +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Save" +msgstr "Speichern" + +#: engines/dialogs.cpp:301 engines/mohawk/dialogs.cpp:84 +#: engines/mohawk/dialogs.cpp:118 +msgid "~O~K" +msgstr "~O~K" + +#: engines/dialogs.cpp:302 engines/mohawk/dialogs.cpp:85 +#: engines/mohawk/dialogs.cpp:119 +msgid "~C~ancel" +msgstr "~A~bbrechen" + +#: engines/dialogs.cpp:305 +msgid "~K~eys" +msgstr "~T~asten" + +#: engines/scumm/dialogs.cpp:287 +msgid "~P~revious" +msgstr "~Z~urück" + +#: engines/scumm/dialogs.cpp:288 +msgid "~N~ext" +msgstr "~W~eiter" + +#: engines/scumm/dialogs.cpp:289 +#: backends/platform/ds/arm9/source/dsoptions.cpp:59 +msgid "~C~lose" +msgstr "~S~chließen" + +#: engines/mohawk/dialogs.cpp:81 engines/mohawk/dialogs.cpp:115 +msgid "~Z~ip Mode Activated" +msgstr "~Z~ip-Modus aktiviert" + +#: engines/mohawk/dialogs.cpp:82 +msgid "~T~ransitions Enabled" +msgstr "Über~g~änge aktiviert" + +#: engines/mohawk/dialogs.cpp:116 +msgid "~W~ater Effect Enabled" +msgstr "~W~assereffekt aktiviert" + +#: sound/fmopl.cpp:51 +msgid "MAME OPL emulator" +msgstr "MAME-OPL-Emulator" + +#: sound/fmopl.cpp:53 +msgid "DOSBox OPL emulator" +msgstr "DOSBox-OPL-Emulator" + +#: sound/null.h:45 +msgid "No music" +msgstr "Keine Musik" + +#: sound/softsynth/adlib.cpp:1590 +msgid "AdLib Emulator" +msgstr "AdLib-Emulator" + +#: sound/softsynth/mt32.cpp:327 +msgid "Initialising MT-32 Emulator" +msgstr "MT-32-Emulator wird gestartet..." + +#: sound/softsynth/mt32.cpp:541 +msgid "MT-32 Emulator" +msgstr "MT-32-Emulation" + +#: sound/softsynth/pcspk.cpp:142 +msgid "PC Speaker Emulator" +msgstr "PC-Lautsprecher-Emulator" + +#: sound/softsynth/pcspk.cpp:161 +msgid "IBM PCjr Emulator" +msgstr "IBM-PCjr-Emulator" + +#: sound/softsynth/ym2612.cpp:762 +msgid "FM Towns Emulator" +msgstr "FM-Towns-Emulator" + +#: backends/keymapper/remap-dialog.cpp:49 +msgid "Keymap:" +msgstr "Tasten-Layout:" + +#: backends/keymapper/remap-dialog.cpp:66 +msgid " (Active)" +msgstr " (Aktiv)" + +#: backends/keymapper/remap-dialog.cpp:100 +msgid " (Global)" +msgstr " (Global)" + +#: backends/keymapper/remap-dialog.cpp:110 +msgid " (Game)" +msgstr " (Spiel)" + +#: backends/midi/windows.cpp:157 +msgid "Windows MIDI" +msgstr "Windows MIDI" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:60 +msgid "ScummVM Main Menu" +msgstr "ScummVM-Hauptmenü" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:66 +msgid "~L~eft handed mode" +msgstr "~L~inke-Hand-Modus" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:67 +msgid "~I~ndy fight controls" +msgstr "~K~ampfsteuerung für Indiana Jones" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:68 +msgid "Show mouse cursor" +msgstr "Mauszeiger anzeigen" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:69 +msgid "Snap to edges" +msgstr "An Ecken anheften" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:71 +msgid "Touch X Offset" +msgstr "Zu X-Position gehen" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:78 +msgid "Touch Y Offset" +msgstr "Zu Y-Position gehen" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:90 +msgid "Use laptop trackpad-style cursor control" +msgstr "Den Trackpad-Style für Maussteuerung benutzen" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:91 +msgid "Tap for left click, double tap right click" +msgstr "Tippen für Linksklick, Doppeltippen für Rechtsklick" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:93 +msgid "Sensitivity" +msgstr "Empfindlichkeit" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:102 +msgid "Initial top screen scale:" +msgstr "Vergößerung des oberen Bildschirms:" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:108 +msgid "Main screen scaling:" +msgstr "Hauptbildschirm-Skalierung:" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:110 +msgid "Hardware scale (fast, but low quality)" +msgstr "Hardware-Skalierung (schnell, aber schlechte Qualität)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:111 +msgid "Software scale (good quality, but slower)" +msgstr "Software-Skalierung (gute Qualität, aber langsamer)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:112 +msgid "Unscaled (you must scroll left and right)" +msgstr "Nicht skalieren (Sie müssen nach links und nach rechts scrollen)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:114 +msgid "Brightness:" +msgstr "Helligkeit:" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:124 +msgid "High quality audio (slower) (reboot)" +msgstr "Hohe Audioqualität (lansamer) (erfordert Neustart)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:125 +msgid "Disable power off" +msgstr "Stromsparmodus abschalten" + +#: backends/platform/iphone/osys_events.cpp:339 +msgid "Touchpad mode enabled." +msgstr "Touchpad-Modus aktiviert." + +#: backends/platform/iphone/osys_events.cpp:341 +msgid "Touchpad mode disabled." +msgstr "Touchpad-Modus ausgeschaltet." + +#: backends/platform/sdl/graphics.cpp:40 +#: backends/platform/wince/wince-sdl.cpp:111 +#: backends/platform/wince/wince-sdl.cpp:118 +msgid "Normal (no scaling)" +msgstr "Normal (keine Skalierung)" + +#: backends/platform/symbian/src/SymbianActions.cpp:41 +#: backends/platform/wince/CEActionsSmartphone.cpp:38 +msgid "Up" +msgstr "Hoch" + +#: backends/platform/symbian/src/SymbianActions.cpp:42 +#: backends/platform/wince/CEActionsSmartphone.cpp:39 +msgid "Down" +msgstr "Runter" + +#: backends/platform/symbian/src/SymbianActions.cpp:43 +#: backends/platform/wince/CEActionsSmartphone.cpp:40 +msgid "Left" +msgstr "Links" + +#: backends/platform/symbian/src/SymbianActions.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:41 +msgid "Right" +msgstr "Rechts" + +#: backends/platform/symbian/src/SymbianActions.cpp:45 +#: backends/platform/wince/CEActionsPocket.cpp:59 +#: backends/platform/wince/CEActionsSmartphone.cpp:42 +msgid "Left Click" +msgstr "Linksklick" + +#: backends/platform/symbian/src/SymbianActions.cpp:46 +#: backends/platform/wince/CEActionsSmartphone.cpp:43 +msgid "Right Click" +msgstr "Rechtsklick" + +#: backends/platform/symbian/src/SymbianActions.cpp:49 +#: backends/platform/wince/CEActionsSmartphone.cpp:46 +msgid "Zone" +msgstr "Zone" + +#: backends/platform/symbian/src/SymbianActions.cpp:50 +#: backends/platform/wince/CEActionsPocket.cpp:53 +#: backends/platform/wince/CEActionsSmartphone.cpp:47 +msgid "Multi Function" +msgstr "Multifunktion" + +#: backends/platform/symbian/src/SymbianActions.cpp:51 +msgid "Swap character" +msgstr "Figur wechseln" + +#: backends/platform/symbian/src/SymbianActions.cpp:52 +msgid "Skip text" +msgstr "Text überspringen" + +#: backends/platform/symbian/src/SymbianActions.cpp:54 +msgid "Fast mode" +msgstr "Schneller Modus" + +#: backends/platform/symbian/src/SymbianActions.cpp:55 +#: backends/platform/wince/CEActionsPocket.cpp:43 +#: backends/platform/wince/CEActionsSmartphone.cpp:51 +msgid "Quit" +msgstr "Beenden" + +#: backends/platform/symbian/src/SymbianActions.cpp:56 +msgid "Debugger" +msgstr "Debugger" + +#: backends/platform/symbian/src/SymbianActions.cpp:57 +msgid "Global menu" +msgstr "Hauptmenü" + +#: backends/platform/symbian/src/SymbianActions.cpp:58 +msgid "Virtual keyboard" +msgstr "Virtuelle Tastatur" + +#: backends/platform/symbian/src/SymbianActions.cpp:59 +msgid "Key mapper" +msgstr "Tasten zuordnen" + +#: backends/platform/symbian/src/SymbianOS.cpp:446 +msgid "Do you want to quit ?" +msgstr "Möchten Sie beenden?" + +#: backends/platform/wii/options.cpp:51 +msgid "Video" +msgstr "Video" + +#: backends/platform/wii/options.cpp:54 +msgid "Current video mode:" +msgstr "Aktueller Videomodus:" + +#: backends/platform/wii/options.cpp:56 +msgid "Double-strike" +msgstr "Doppelzeilen (kein Zeilensprungverfahren)" + +#: backends/platform/wii/options.cpp:60 +msgid "Horizontal underscan:" +msgstr "Horizontale Bildverkleinerung:" + +#: backends/platform/wii/options.cpp:66 +msgid "Vertical underscan:" +msgstr "Vertikale Bildverkleinerung:" + +#: backends/platform/wii/options.cpp:71 +msgid "Input" +msgstr "Eingabe" + +#: backends/platform/wii/options.cpp:74 +msgid "GC Pad sensitivity:" +msgstr "GC-Pad-Empfindlichkeit:" + +#: backends/platform/wii/options.cpp:80 +msgid "GC Pad acceleration:" +msgstr "GC-Pad-Beschleunigung:" + +#: backends/platform/wii/options.cpp:86 +msgid "DVD" +msgstr "DVD" + +#: backends/platform/wii/options.cpp:89 backends/platform/wii/options.cpp:101 +msgid "Status:" +msgstr "Status:" + +#: backends/platform/wii/options.cpp:90 backends/platform/wii/options.cpp:102 +msgid "Unknown" +msgstr "Unbekannt" + +#: backends/platform/wii/options.cpp:93 +msgid "Mount DVD" +msgstr "DVD einbinden" + +#: backends/platform/wii/options.cpp:94 +msgid "Unmount DVD" +msgstr "DVD aushängen" + +#: backends/platform/wii/options.cpp:98 +msgid "SMB" +msgstr "SMB" + +#: backends/platform/wii/options.cpp:106 +msgid "Server:" +msgstr "Server:" + +#: backends/platform/wii/options.cpp:110 +msgid "Share:" +msgstr "Öffentliches Verzeichnis:" + +#: backends/platform/wii/options.cpp:114 +msgid "Username:" +msgstr "Benutzername:" + +#: backends/platform/wii/options.cpp:118 +msgid "Password:" +msgstr "Passwort:" + +#: backends/platform/wii/options.cpp:121 +msgid "Init network" +msgstr "Netzwerk starten" + +#: backends/platform/wii/options.cpp:123 +msgid "Mount SMB" +msgstr "SMB einbinden" + +#: backends/platform/wii/options.cpp:124 +msgid "Unmount SMB" +msgstr "SMB aushängen" + +#: backends/platform/wii/options.cpp:145 +msgid "DVD Mounted successfully" +msgstr "DVD erfolgreich eingebunden" + +#: backends/platform/wii/options.cpp:148 +msgid "Error while mounting the DVD" +msgstr "Fehler beim Einbinden der DVD" + +#: backends/platform/wii/options.cpp:150 +msgid "DVD not mounted" +msgstr "DVD nicht eingebunden" + +#: backends/platform/wii/options.cpp:163 +msgid "Network up, share mounted" +msgstr "Netzwerk gestartet, öffentliches Verzeichnis eingebunden" + +#: backends/platform/wii/options.cpp:165 +msgid "Network up" +msgstr "Netzwerk gestartet" + +#: backends/platform/wii/options.cpp:168 +msgid ", error while mounting the share" +msgstr ", Fehler beim Einbinden des öffentlichen Verzeichnisses" + +#: backends/platform/wii/options.cpp:170 +msgid ", share not mounted" +msgstr ", öffentliches Verzeichnis nicht eingebunden" + +#: backends/platform/wii/options.cpp:176 +msgid "Network down" +msgstr "Netzwerk ist aus." + +#: backends/platform/wii/options.cpp:180 +msgid "Initialising network" +msgstr "Netzwerk wird gestartet..." + +#: backends/platform/wii/options.cpp:184 +msgid "Timeout while initialising network" +msgstr "Zeitüberschreitung beim Starten des Netzwerks" + +#: backends/platform/wii/options.cpp:188 +#, c-format +msgid "Network not initialsed (%d)" +msgstr "Netzwerk nicht gestartet (%d)" + +#: backends/platform/wince/CEActionsPocket.cpp:45 +msgid "Hide Toolbar" +msgstr "Werkzeugleiste verbergen" + +#: backends/platform/wince/CEActionsPocket.cpp:46 +msgid "Show Keyboard" +msgstr "Tastatur zeigen" + +#: backends/platform/wince/CEActionsPocket.cpp:47 +msgid "Sound on/off" +msgstr "Ton ein/aus" + +#: backends/platform/wince/CEActionsPocket.cpp:48 +msgid "Right click" +msgstr "Rechtsklick" + +#: backends/platform/wince/CEActionsPocket.cpp:49 +msgid "Show/Hide Cursor" +msgstr "Cursor zeigen/verbergen" + +#: backends/platform/wince/CEActionsPocket.cpp:50 +msgid "Free look" +msgstr "Freie Ansicht" + +#: backends/platform/wince/CEActionsPocket.cpp:51 +msgid "Zoom up" +msgstr "Herauszoomen" + +#: backends/platform/wince/CEActionsPocket.cpp:52 +msgid "Zoom down" +msgstr "Hineinzoomen" + +#: backends/platform/wince/CEActionsPocket.cpp:54 +#: backends/platform/wince/CEActionsSmartphone.cpp:48 +msgid "Bind Keys" +msgstr "Tasten zuweisen" + +#: backends/platform/wince/CEActionsPocket.cpp:55 +msgid "Cursor Up" +msgstr "Zeiger hoch" + +#: backends/platform/wince/CEActionsPocket.cpp:56 +msgid "Cursor Down" +msgstr "Zeiger runter" + +#: backends/platform/wince/CEActionsPocket.cpp:57 +msgid "Cursor Left" +msgstr "Zeiger nach links" + +#: backends/platform/wince/CEActionsPocket.cpp:58 +msgid "Cursor Right" +msgstr "Zeiger nach rechts" + +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Do you want to load or save the game?" +msgstr "Möchten Sie ein Spiel laden oder speichern?" + +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +msgid " Are you sure you want to quit ? " +msgstr " Möchten Sie wirklich beenden? " + +#: backends/platform/wince/CEActionsSmartphone.cpp:49 +msgid "Keyboard" +msgstr "Tastatur" + +#: backends/platform/wince/CEActionsSmartphone.cpp:50 +msgid "Rotate" +msgstr "Drehen" + +#: backends/platform/wince/CELauncherDialog.cpp:58 +msgid "Using SDL driver " +msgstr "SDL-Treiber verwenden" + +#: backends/platform/wince/CELauncherDialog.cpp:62 +msgid "Display " +msgstr "Anzeige" + +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "Do you want to perform an automatic scan ?" +msgstr "Möchten Sie eine automatische Durchsuchung vornehmen?" + +#~ msgid "Failed to load any GUI theme, aborting" +#~ msgstr "Fehler: Konnte kein Benutzeroberflächen-Thema laden. Abbruch..." + +#~ msgid "User picked target '%s' (gameid '%s')...\n" +#~ msgstr "Gewähltes Ziel: \"%s\" (Spielkennung \"%s\")...\n" + +#~ msgid " Looking for a plugin supporting this gameid... " +#~ msgstr "" +#~ " Suche nach einer Erweiterung, die diese Spielkennung unterstützt..." + +#~ msgid "failed\n" +#~ msgstr "fehlgeschlagen\n" + +#~ msgid "" +#~ "%s is an invalid gameid. Use the --list-games option to list supported " +#~ "gameid" +#~ msgstr "" +#~ "%s ist eine ungültige Spielkennung. Benutzen Sie die Option --list-games " +#~ "zum Anzeigen der unterstützten Spielkennungen." + +#~ msgid " Starting '%s'\n" +#~ msgstr " Starte \"%s\"\n" + +#~ msgid "%s failed to instantiate engine: %s (target '%s', path '%s')" +#~ msgstr "%s konnte Engine nicht starten: %s (Ziel \"%s\", Pfad \"%s\")" + +#~ msgid "Ok" +#~ msgstr "OK" + +#~ msgid "Music driver:" +#~ msgstr "Musiktreiber:" + +#~ msgid "ALSA" +#~ msgstr "ALSA" + +#~ msgid "Atari ST MIDI" +#~ msgstr "Atari ST MIDI" + +#~ msgid "SEQ" +#~ msgstr "SEQ" + +#~ msgid "DMedia" +#~ msgstr "DMedia" + +#~ msgid "CAMD" +#~ msgstr "CAMD" + +#~ msgid "CoreAudio" +#~ msgstr "CoreAudio" + +#~ msgid "CoreMIDI" +#~ msgstr "CoreMIDI" + +#~ msgid "Yamaha Pa1" +#~ msgstr "Yamaha Pa1" + +#~ msgid "Tapwave Zodiac" +#~ msgstr "Tapwave Zodiac" + +#~ msgid "FluidSynth" +#~ msgstr "FluidSynth" + +#~ msgid "AdLib" +#~ msgstr "AdLib" + +#~ msgid "IBM PCjr" +#~ msgstr "IBM PCjr" + +#~ msgid "Creative Music System" +#~ msgstr "Creative-Musik-System" + +#~ msgid "TiMidity" +#~ msgstr "TiMidity" diff --git a/po/fr_FR.po b/po/fr_FR.po new file mode 100644 index 0000000000..d4e9e9f53c --- /dev/null +++ b/po/fr_FR.po @@ -0,0 +1,1486 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR ScummVM Team +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: ScummVM 1.2.0svn\n" +"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n" +"POT-Creation-Date: 2010-07-12 17:44+0200\n" +"PO-Revision-Date: 2010-07-09 18:17+0100\n" +"Last-Translator: Thierry Crozat <criezy@scummvm.org>\n" +"Language-Team: French <scummvm-devel@lists.sf.net>\n" +"Language: Francais\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n>1;\n" + +#: gui/about.cpp:96 +#, c-format +msgid "(built on %s)" +msgstr "(compilé sur %s)" + +#: gui/about.cpp:103 +msgid "Features compiled in:" +msgstr "Options incluses:" + +#: gui/about.cpp:112 +msgid "Available engines:" +msgstr "Moteurs disponibles:" + +#: gui/browser.cpp:69 +msgid "Go up" +msgstr "Remonter" + +#: gui/browser.cpp:69 +msgid "Go to previous directory level" +msgstr "Remonte d'un niveau dans la hiérarchie de répertoire" + +#: gui/browser.cpp:70 gui/chooser.cpp:49 gui/KeysDialog.cpp:46 +#: gui/launcher.cpp:266 gui/massadd.cpp:95 gui/options.cpp:972 +#: gui/saveload.cpp:65 gui/saveload.cpp:157 gui/themebrowser.cpp:56 +#: backends/platform/wii/options.cpp:48 +msgid "Cancel" +msgstr "Annuler" + +#: gui/browser.cpp:71 gui/chooser.cpp:50 gui/themebrowser.cpp:57 +msgid "Choose" +msgstr "Choisir" + +#: gui/GuiManager.cpp:102 backends/keymapper/remap-dialog.cpp:54 +msgid "Close" +msgstr "Fermer" + +#: gui/GuiManager.cpp:105 +msgid "Mouse click" +msgstr "Clic de souris" + +#: gui/GuiManager.cpp:108 base/main.cpp:285 +msgid "Display keyboard" +msgstr "Afficher le clavier" + +#: gui/GuiManager.cpp:111 base/main.cpp:288 +msgid "Remap keys" +msgstr "Changer l'affectation des touches" + +#: gui/KeysDialog.cpp:44 +msgid "Map" +msgstr "Affecter" + +#: gui/KeysDialog.cpp:45 gui/launcher.cpp:267 gui/launcher.cpp:873 +#: gui/launcher.cpp:877 gui/massadd.cpp:92 gui/options.cpp:973 +#: backends/platform/wii/options.cpp:47 +#: backends/platform/wince/CELauncherDialog.cpp:56 +msgid "OK" +msgstr "OK" + +#: gui/KeysDialog.cpp:52 +msgid "Select an action and click 'Map'" +msgstr "Selectionez une action et cliquez 'Affecter'" + +#: gui/KeysDialog.cpp:83 gui/KeysDialog.cpp:105 gui/KeysDialog.cpp:144 +#, c-format +msgid "Associated key : %s" +msgstr "Touche associée: %s" + +#: gui/KeysDialog.cpp:85 gui/KeysDialog.cpp:107 gui/KeysDialog.cpp:146 +#, c-format +msgid "Associated key : none" +msgstr "Touche associée: aucune" + +#: gui/KeysDialog.cpp:93 +msgid "Please select an action" +msgstr "Selectionnez une action" + +#: gui/KeysDialog.cpp:109 +msgid "Press the key to associate" +msgstr "Appuyez sur la touche à associer" + +#: gui/KeysDialog.cpp:148 +msgid "Choose an action to map" +msgstr "Sélectionnez une action à affecter" + +#: gui/launcher.cpp:170 +msgid "Game" +msgstr "Jeu" + +#: gui/launcher.cpp:173 +msgid "ID:" +msgstr "ID:" + +#: gui/launcher.cpp:173 gui/launcher.cpp:174 +msgid "" +"Short game identifier used for referring to savegames and running the game " +"from the command line" +msgstr "" +"ID compact du jeu utilisé pour identifier les sauvegardes et démarrer le jeu " +"depuis la ligne de commande" + +#: gui/launcher.cpp:177 +msgid "Name:" +msgstr "Nom:" + +#: gui/launcher.cpp:177 gui/launcher.cpp:178 +msgid "Full title of the game" +msgstr "Nom complet du jeu" + +#: gui/launcher.cpp:181 +msgid "Language:" +msgstr "Langue:" + +#: gui/launcher.cpp:181 gui/launcher.cpp:182 +msgid "" +"Language of the game. This will not turn your Spanish game version into " +"English" +msgstr "" +"Langue du jeu. Cela ne traduira pas en anglais par magie votre version " +"espagnole du jeu." + +#: gui/launcher.cpp:183 gui/launcher.cpp:194 gui/options.cpp:80 +#: gui/options.cpp:617 gui/options.cpp:627 gui/options.cpp:943 +#: sound/null.cpp:42 +msgid "<default>" +msgstr "<defaut>" + +#: gui/launcher.cpp:192 +msgid "Platform:" +msgstr "Plateforme:" + +#: gui/launcher.cpp:192 gui/launcher.cpp:193 +msgid "Platform the game was originally designed for" +msgstr "Plateforme pour laquelle votre jeu a été conçu" + +#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867 +msgid "Graphics" +msgstr "Graphique" + +#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867 +msgid "GFX" +msgstr "GFX" + +#: gui/launcher.cpp:206 +msgid "Override global graphic settings" +msgstr "Utiliser des réglages graphiques spécifiques à ce jeux" + +#: gui/launcher.cpp:213 gui/options.cpp:873 +msgid "Audio" +msgstr "Audio" + +#: gui/launcher.cpp:215 +msgid "Override global audio settings" +msgstr "Utiliser des réglages audio spécifiques à ce jeux" + +#: gui/launcher.cpp:223 gui/options.cpp:877 +msgid "Volume" +msgstr "Volume" + +#: gui/launcher.cpp:225 +msgid "Override global volume settings" +msgstr "Utiliser des réglages de volume sonore spécifiques à ce jeux" + +#: gui/launcher.cpp:232 gui/options.cpp:885 +msgid "MIDI" +msgstr "MIDI" + +#: gui/launcher.cpp:234 +msgid "Override global MIDI settings" +msgstr "Utiliser des réglages MIDI spécifiques à ce jeux" + +#: gui/launcher.cpp:244 gui/options.cpp:891 +msgid "Paths" +msgstr "Chemins" + +#: gui/launcher.cpp:250 +msgid "Game Path:" +msgstr "Chemin du Jeu:" + +#: gui/launcher.cpp:254 gui/options.cpp:904 +msgid "Extra Path:" +msgstr "Extra:" + +#: gui/launcher.cpp:254 gui/launcher.cpp:255 +msgid "Specifies path to additional data used the game" +msgstr "Définie un chemin vers des données suplémentaires utilisées par le jeu" + +#: gui/launcher.cpp:258 +msgid "Save Path:" +msgstr "Sauvegardes:" + +#: gui/launcher.cpp:258 gui/launcher.cpp:259 gui/options.cpp:898 +#: gui/options.cpp:899 +msgid "Specifies where your savegames are put" +msgstr "Définie l'emplacement où les fichiers de sauvegarde sont créés" + +#: gui/launcher.cpp:275 gui/launcher.cpp:353 gui/launcher.cpp:398 +#: gui/options.cpp:245 gui/options.cpp:400 gui/options.cpp:486 +#: gui/options.cpp:545 gui/options.cpp:706 gui/options.cpp:902 +#: gui/options.cpp:905 gui/options.cpp:909 gui/options.cpp:996 +#: gui/options.cpp:1002 gui/options.cpp:1008 gui/options.cpp:1016 +#: gui/options.cpp:1040 gui/options.cpp:1044 gui/options.cpp:1050 +#: gui/options.cpp:1057 gui/options.cpp:1156 +msgid "None" +msgstr "Aucun" + +#: gui/launcher.cpp:280 gui/launcher.cpp:357 +#: backends/platform/wii/options.cpp:56 +msgid "Default" +msgstr "Défaut" + +#: gui/launcher.cpp:391 gui/options.cpp:1150 +msgid "Select SoundFont" +msgstr "Choisir une banque de sons" + +#: gui/launcher.cpp:410 gui/launcher.cpp:548 +msgid "Select directory with game data" +msgstr "Sélectionner le répertoire contenant les données du jeu" + +#: gui/launcher.cpp:428 +msgid "Select additional game directory" +msgstr "Sélectionner un répertoire supplémentaire" + +#: gui/launcher.cpp:440 +msgid "Select directory for saved games" +msgstr "Sélectionner le répertoire pour les sauvegardes" + +#: gui/launcher.cpp:459 +msgid "This game ID is already taken. Please choose another one." +msgstr "Cet ID est déjà utilisé par un autre jeu. Choisissez en un autre svp." + +#: gui/launcher.cpp:500 engines/dialogs.cpp:113 +msgid "~Q~uit" +msgstr "~Q~uitter" + +#: gui/launcher.cpp:500 +msgid "Quit ScummVM" +msgstr "Quitter ScummVM" + +#: gui/launcher.cpp:501 +msgid "A~b~out..." +msgstr "À ~P~ropos..." + +#: gui/launcher.cpp:501 +msgid "About ScummVM" +msgstr "À propos de ScummVM" + +#: gui/launcher.cpp:502 +msgid "~O~ptions..." +msgstr "~O~ptions..." + +#: gui/launcher.cpp:502 +msgid "Change global ScummVM options" +msgstr "Change les options globales de ScummVM" + +#: gui/launcher.cpp:504 +msgid "~S~tart" +msgstr "~D~émarrer" + +#: gui/launcher.cpp:504 +msgid "Start selected game" +msgstr "Démarre le jeu sélectionné" + +#: gui/launcher.cpp:507 +msgid "~L~oad..." +msgstr "~C~harger" + +#: gui/launcher.cpp:507 +msgid "Load savegame for selected game" +msgstr "Charge une sauvegarde pour le jeu sélectionné" + +#: gui/launcher.cpp:511 +msgid "~A~dd Game..." +msgstr "~A~jouter..." + +#: gui/launcher.cpp:511 +msgid "Hold Shift for Mass Add" +msgstr "" +"Ajoute un jeu à la Liste. Maintenez Shift enfoncée pour un Ajout Massif" + +#: gui/launcher.cpp:513 +msgid "~E~dit Game..." +msgstr "~E~diter..." + +#: gui/launcher.cpp:513 +msgid "Change game options" +msgstr "Change les options du jeu" + +#: gui/launcher.cpp:515 +msgid "~R~emove Game" +msgstr "~S~upprimer" + +#: gui/launcher.cpp:515 +msgid "Remove game from the list. The game data files stay intact" +msgstr "Supprime le jeu de la liste. Les fichiers sont conservés" + +#: gui/launcher.cpp:522 +msgid "Search in game list" +msgstr "Recherche dans la liste de jeux" + +#: gui/launcher.cpp:526 gui/launcher.cpp:1037 +msgid "Search:" +msgstr "Filtre:" + +#: gui/launcher.cpp:529 gui/options.cpp:707 +msgid "Clear value" +msgstr "Effacer la valeur" + +#: gui/launcher.cpp:551 engines/dialogs.cpp:117 +msgid "Load game:" +msgstr "Charger le jeu:" + +#: gui/launcher.cpp:551 engines/dialogs.cpp:117 +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Load" +msgstr "Charger" + +#: gui/launcher.cpp:660 +msgid "" +"Do you really want to run the mass game detector? This could potentially add " +"a huge number of games." +msgstr "" +"Voulez-vous vraiment lancer la détection automatique des jeux? Cela peut " +"potentiellement ajouter un grand nombre de jeux." + +#: gui/launcher.cpp:661 gui/launcher.cpp:810 +#: backends/platform/symbian/src/SymbianOS.cpp:446 +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "Yes" +msgstr "Oui" + +#: gui/launcher.cpp:661 gui/launcher.cpp:810 +#: backends/platform/symbian/src/SymbianOS.cpp:446 +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "No" +msgstr "Non" + +#: gui/launcher.cpp:708 +msgid "ScummVM couldn't open the specified directory!" +msgstr "ScummVM n'a pas pu ouvrir le répertoire sélectionné." + +#: gui/launcher.cpp:720 +msgid "ScummVM could not find any game in the specified directory!" +msgstr "ScummVM n'a pas trouvé de jeux dans le répertoire sélectionné." + +#: gui/launcher.cpp:734 +msgid "Pick the game:" +msgstr "Choisissez le jeu:" + +#: gui/launcher.cpp:810 +msgid "Do you really want to remove this game configuration?" +msgstr "Voulez-vous vraiment supprimer ce jeu?" + +#: gui/launcher.cpp:873 +msgid "This game does not support loading games from the launcher." +msgstr "" +"Le chargement de sauvegarde depuis le lanceur n'est pas supporté pour ce jeu." + +#: gui/launcher.cpp:877 +msgid "ScummVM could not find any engine capable of running the selected game!" +msgstr "ScummVM n'a pas pu trouvé de moteur pour lancer le jeu sélectionné." + +#: gui/launcher.cpp:989 +msgid "Mass Add..." +msgstr "Ajout Massif..." + +#: gui/launcher.cpp:990 +msgid "Add Game..." +msgstr "Ajouter..." + +#: gui/massadd.cpp:79 gui/massadd.cpp:82 +msgid "... progress ..." +msgstr "... en cours ..." + +#: gui/massadd.cpp:244 +msgid "Scan complete!" +msgstr "Examen terminé!" + +#: gui/massadd.cpp:247 +#, c-format +msgid "Discovered %d new games." +msgstr "%d nouveaux jeux trouvés." + +#: gui/massadd.cpp:251 +#, c-format +msgid "Scanned %d directories ..." +msgstr "%d répertoires examinés ..." + +#: gui/massadd.cpp:254 +#, c-format +msgid "Discovered %d new games ..." +msgstr "%d nouveaux jeux trouvés ..." + +#: gui/options.cpp:78 +msgid "Never" +msgstr "Jamais" + +#: gui/options.cpp:78 +msgid "every 5 mins" +msgstr "Toutes les 5 mins" + +#: gui/options.cpp:78 +msgid "every 10 mins" +msgstr "Toutes les 10 mins" + +#: gui/options.cpp:78 +msgid "every 15 mins" +msgstr "Toutes les 15 mins" + +#: gui/options.cpp:78 +msgid "every 30 mins" +msgstr "Toutes les 30 mins" + +#: gui/options.cpp:80 +msgid "8 kHz" +msgstr "8 kHz" + +#: gui/options.cpp:80 +msgid "11kHz" +msgstr "11 kHz" + +#: gui/options.cpp:80 +msgid "22 kHz" +msgstr "22 kHz" + +#: gui/options.cpp:80 +msgid "44 kHz" +msgstr "44 kHz" + +#: gui/options.cpp:80 +msgid "48 kHz" +msgstr "48 kHz" + +#: gui/options.cpp:614 +msgid "Graphics mode:" +msgstr "Mode graphique:" + +#: gui/options.cpp:625 +msgid "Render mode:" +msgstr "Mode de rendu:" + +#: gui/options.cpp:625 gui/options.cpp:626 +msgid "Special dithering modes supported by some games" +msgstr "Mode spécial de tramage supporté par certains jeux" + +#: gui/options.cpp:635 +msgid "Fullscreen mode" +msgstr "Plein écran" + +#: gui/options.cpp:638 +msgid "Aspect ratio correction" +msgstr "Correction du rapport d'aspect" + +#: gui/options.cpp:638 +msgid "Correct aspect ratio for 320x200 games" +msgstr "Corrige le rapport d'aspect pour les jeu 320x200" + +#: gui/options.cpp:645 +msgid "Preferred Device:" +msgstr "Sortie Préféré:" + +#: gui/options.cpp:645 +msgid "Music Device:" +msgstr "Sortie Audio:" + +#: gui/options.cpp:645 +msgid "Specifies preferred sound device or sound card emulator" +msgstr "" +"Spécifie le périphérique de sortie audio ou l'émulateur de carte audio " +"préféré" + +#: gui/options.cpp:645 gui/options.cpp:646 +msgid "Specifies output sound device or sound card emulator" +msgstr "Spécifie le périphérique de sortie audio ou l'émulateur de carte audio" + +#: gui/options.cpp:648 +#, fuzzy +msgid "MT-32 Device:" +msgstr "Sortie MT-32:" + +#: gui/options.cpp:648 +msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output" +msgstr "" +"Spécifie le périphérique audio par défaut pour la sortie Roland MT-32/LAPC1/" +"CM32l/CM64" + +#: gui/options.cpp:650 +msgid "GM Device:" +msgstr "Sortie GM:" + +#: gui/options.cpp:650 +msgid "Specifies default sound device for General MIDI output" +msgstr "Spécifie le périphérique audio par défaut pour la sortie General MIDI" + +#: gui/options.cpp:682 +msgid "AdLib emulator:" +msgstr "Émulateur AdLib:" + +#: gui/options.cpp:682 gui/options.cpp:683 +msgid "AdLib is used for music in many games" +msgstr "AdLib est utilisé pour la musique dans de nombreux jeux" + +#: gui/options.cpp:693 +msgid "Output rate:" +msgstr "Fréquence:" + +#: gui/options.cpp:693 gui/options.cpp:694 +msgid "" +"Higher value specifies better sound quality but may be not supported by your " +"soundcard" +msgstr "" +"Une valeur plus élevée donne une meilleure qualité audio mais peut ne pas " +"être supporté par votre carte son" + +#: gui/options.cpp:705 +msgid "SoundFont:" +msgstr "Banque de sons:" + +#: gui/options.cpp:705 gui/options.cpp:706 +msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity" +msgstr "" +"La banque de sons est utilisée par certaines cartes audio, Fluidsynth et " +"Timidity" + +#: gui/options.cpp:710 +msgid "Mixed AdLib/MIDI mode" +msgstr "Mode mixe AdLib/MIDI" + +#: gui/options.cpp:710 +msgid "Use both MIDI and AdLib sound generation" +msgstr "Utiliser à la fois MIDI et AdLib" + +#: gui/options.cpp:713 +msgid "True Roland MT-32 (disable GM emulation)" +msgstr "Roland MT-32 exacte (désactive l'émulation GM)" + +#: gui/options.cpp:713 +msgid "" +"Check if you want to use your real hardware Roland-compatible sound device " +"connected to your computer" +msgstr "" +"Vérifie si vous voulez utiliser un périphérique audio compatible Roland " +"connecté à l'ordinateur" + +#: gui/options.cpp:716 +msgid "Enable Roland GS Mode" +msgstr "Activer le mode Roland GS" + +#: gui/options.cpp:716 +msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack" +msgstr "Désactiver la conversion des pistes MT-32 en General MIDI" + +#: gui/options.cpp:719 +msgid "MIDI gain:" +msgstr "Gain MIDI:" + +#: gui/options.cpp:732 +msgid "Text and Speech:" +msgstr "Dialogue:" + +#: gui/options.cpp:737 gui/options.cpp:743 +msgid "Speech" +msgstr "Audio" + +#: gui/options.cpp:738 gui/options.cpp:744 +msgid "Subtitles" +msgstr "Sous-titres" + +#: gui/options.cpp:739 gui/options.cpp:745 +msgid "Both" +msgstr "Les deux" + +#: gui/options.cpp:743 +msgid "Spch" +msgstr "Audio" + +#: gui/options.cpp:744 +msgid "Subs" +msgstr "Subs" + +#: gui/options.cpp:745 +msgid "Show subtitles and play speech" +msgstr "Affiche les sous-titres et joue les dialogues audio" + +#: gui/options.cpp:749 +msgid "Subtitle speed:" +msgstr "Vitesse des ST:" + +#: gui/options.cpp:761 +msgid "Music volume:" +msgstr "Volume Musique:" + +#: gui/options.cpp:768 +msgid "Mute All" +msgstr "Silence" + +#: gui/options.cpp:771 +msgid "SFX volume:" +msgstr "Volume Bruitage:" + +#: gui/options.cpp:771 gui/options.cpp:772 +msgid "Special sound effects volume" +msgstr "Volume des effets spéciaux sonores" + +#: gui/options.cpp:778 +msgid "Speech volume:" +msgstr "Volume Dialogues:" + +#: gui/options.cpp:898 +msgid "Save Path: " +msgstr "Sauvegardes:" + +#: gui/options.cpp:901 +msgid "Theme Path:" +msgstr "Thèmes:" + +#: gui/options.cpp:904 gui/options.cpp:905 +msgid "Specifies path to additional data used by all games or ScummVM" +msgstr "" +"Spécifie un chemin vers des données supplémentaires utilisées par tous les " +"jeux ou ScummVM" + +#: gui/options.cpp:908 +msgid "Plugins Path:" +msgstr "Plugins:" + +#: gui/options.cpp:913 +msgid "Misc" +msgstr "Divers" + +#: gui/options.cpp:915 +msgid "Theme:" +msgstr "Thème:" + +#: gui/options.cpp:919 +msgid "GUI Renderer:" +msgstr "Interface:" + +#: gui/options.cpp:925 +msgid "Autosave:" +msgstr "Sauvegarde auto:" + +#: gui/options.cpp:933 +msgid "Keys" +msgstr "Touches" + +#: gui/options.cpp:940 +msgid "GUI Language:" +msgstr "Langue:" + +#: gui/options.cpp:940 +msgid "Language of ScummVM GUI" +msgstr "Langue de l'interface graphique de ScummVM" + +#: gui/options.cpp:945 +msgid "English" +msgstr "Anglais" + +#: gui/options.cpp:1089 +msgid "You have to restart ScummVM to take the effect." +msgstr "" +"Vous devez relancer ScummVM pour que le changement soit pris en compte." + +#: gui/options.cpp:1102 +msgid "Select directory for savegames" +msgstr "Sélectionner le répertoire pour les sauvegardes" + +#: gui/options.cpp:1109 +msgid "The chosen directory cannot be written to. Please select another one." +msgstr "" +"Le répertoire sélectionné est vérouillé en écriture. Sélectionnez un autre " +"répertoire." + +#: gui/options.cpp:1118 +msgid "Select directory for GUI themes" +msgstr "Sélectionner le répertoire des thèmes d'interface" + +#: gui/options.cpp:1128 +msgid "Select directory for extra files" +msgstr "Sélectionner le répertoire pour les fichiers suplémentaires" + +#: gui/options.cpp:1139 +msgid "Select directory for plugins" +msgstr "Sélectionner le répertoire des plugins" + +#: gui/saveload.cpp:60 gui/saveload.cpp:241 +msgid "No date saved" +msgstr "Date non sauvée" + +#: gui/saveload.cpp:61 gui/saveload.cpp:242 +msgid "No time saved" +msgstr "Heure non sauvée" + +#: gui/saveload.cpp:62 gui/saveload.cpp:243 +msgid "No playtime saved" +msgstr "Durée de jeu non sauvée" + +#: gui/saveload.cpp:69 gui/saveload.cpp:157 +msgid "Delete" +msgstr "Supprimer" + +#: gui/saveload.cpp:156 +msgid "Do you really want to delete this savegame?" +msgstr "Voulez-vous vraiment supprimer cette sauvegarde?" + +#: gui/saveload.cpp:265 +msgid "Date: " +msgstr "Date:" + +#: gui/saveload.cpp:268 +msgid "Time: " +msgstr "Heure:" + +#: gui/saveload.cpp:273 +msgid "Playtime: " +msgstr "Durée de jeu:" + +#: gui/saveload.cpp:286 gui/saveload.cpp:353 +msgid "Untitled savestate" +msgstr "Sauvegarde sans nom" + +#: gui/themebrowser.cpp:46 +msgid "Select a Theme" +msgstr "Sélectionnez un Thème" + +#: gui/ThemeEngine.cpp:337 +msgid "Disabled GFX" +msgstr "GFX désactivé" + +#: gui/ThemeEngine.cpp:338 +msgid "Standard Renderer (16bpp)" +msgstr "Standard (16bpp)" + +#: gui/ThemeEngine.cpp:340 +msgid "Antialiased Renderer (16bpp)" +msgstr "Anti-crénelé (16 bpp)" + +#: base/main.cpp:205 +#, c-format +msgid "Engine does not support debug level '%s'" +msgstr "Le niveau de debug '%s' n'est pas supporté par ce moteur de jeu" + +#: base/main.cpp:273 +msgid "Menu" +msgstr "Menu" + +#: base/main.cpp:276 backends/platform/symbian/src/SymbianActions.cpp:48 +#: backends/platform/wince/CEActionsPocket.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:45 +msgid "Skip" +msgstr "Passer" + +#: base/main.cpp:279 backends/platform/symbian/src/SymbianActions.cpp:53 +#: backends/platform/wince/CEActionsPocket.cpp:41 +msgid "Pause" +msgstr "Mettre en pause" + +#: base/main.cpp:282 +msgid "Skip line" +msgstr "Passer la phrase" + +#: base/main.cpp:404 +msgid "Error running game:" +msgstr "Erreur lors de l'éxécution du jeu:" + +#: base/main.cpp:430 base/main.cpp:431 +msgid "Could not find any engine capable of running the selected game" +msgstr "Impossible de trouver un moteur pour exécuter le jeu sélectionné" + +#: common/error.cpp:43 +msgid "Invalid Path" +msgstr "Chemin Invalide" + +#: common/error.cpp:44 +msgid "Game Data not found" +msgstr "Fichier de donées introuvable" + +#: common/error.cpp:45 +msgid "Game Id not supported" +msgstr "ID de jeu non supporté" + +#: common/error.cpp:46 +msgid "Unsupported Color Mode" +msgstr "Mode de couleurs non supporté" + +#: common/error.cpp:48 +msgid "Read permission denied" +msgstr "Véroullié en lecture" + +#: common/error.cpp:49 +msgid "Write permission denied" +msgstr "Verrouillé en écriture" + +#: common/error.cpp:52 +msgid "Path not exists" +msgstr "Chemin inexistant" + +#: common/error.cpp:53 +msgid "Path not a directory" +msgstr "Chemin n'est pas un répertoire" + +#: common/error.cpp:54 +msgid "Path not a file" +msgstr "Chemin n'est pas un fichier" + +#: common/error.cpp:56 +msgid "Cannot create file" +msgstr "Impossible de créer le fichier" + +#: common/error.cpp:57 +msgid "Reading failed" +msgstr "Echec de la lecture" + +#: common/error.cpp:58 +msgid "Writing data failed" +msgstr "Echec de l'écriture des données" + +#: common/error.cpp:60 common/error.cpp:71 +msgid "Unknown Error" +msgstr "Erreur inconnue" + +#: common/util.cpp:254 +msgid "Hercules Green" +msgstr "Hercules Vert" + +#: common/util.cpp:255 +msgid "Hercules Amber" +msgstr "Hercules Ambre" + +#: engines/dialogs.cpp:89 +msgid "~R~esume" +msgstr "~R~eprendre" + +#: engines/dialogs.cpp:91 +msgid "~L~oad" +msgstr "~C~harger" + +#: engines/dialogs.cpp:95 +msgid "~S~ave" +msgstr "~S~auver" + +#: engines/dialogs.cpp:99 +msgid "~O~ptions" +msgstr "~O~ptions" + +#: engines/dialogs.cpp:104 +msgid "~H~elp" +msgstr "~A~ide" + +#: engines/dialogs.cpp:107 +msgid "~A~bout" +msgstr "À ~P~ropos" + +#: engines/dialogs.cpp:109 +msgid "~R~eturn to Launcher" +msgstr "Retour au ~L~anceur" + +#: engines/dialogs.cpp:119 +msgid "Save game:" +msgstr "Sauvegarde:" + +#: engines/dialogs.cpp:119 backends/platform/symbian/src/SymbianActions.cpp:47 +#: backends/platform/wince/CEActionsPocket.cpp:42 +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Save" +msgstr "Sauver" + +#: engines/dialogs.cpp:301 engines/mohawk/dialogs.cpp:84 +#: engines/mohawk/dialogs.cpp:118 +msgid "~O~K" +msgstr "~O~K" + +#: engines/dialogs.cpp:302 engines/mohawk/dialogs.cpp:85 +#: engines/mohawk/dialogs.cpp:119 +msgid "~C~ancel" +msgstr "~A~nnuler" + +#: engines/dialogs.cpp:305 +msgid "~K~eys" +msgstr "~T~ouches" + +#: engines/scumm/dialogs.cpp:287 +msgid "~P~revious" +msgstr "~P~récédent" + +#: engines/scumm/dialogs.cpp:288 +msgid "~N~ext" +msgstr "~S~uivant" + +#: engines/scumm/dialogs.cpp:289 +#: backends/platform/ds/arm9/source/dsoptions.cpp:59 +msgid "~C~lose" +msgstr "~F~ermer" + +#: engines/mohawk/dialogs.cpp:81 engines/mohawk/dialogs.cpp:115 +msgid "~Z~ip Mode Activated" +msgstr "Mode ~Z~ip Activé" + +#: engines/mohawk/dialogs.cpp:82 +msgid "~T~ransitions Enabled" +msgstr "T~r~ansitions activé" + +#: engines/mohawk/dialogs.cpp:116 +msgid "~W~ater Effect Enabled" +msgstr "~E~ffets de l'Eau Activés" + +#: sound/fmopl.cpp:51 +msgid "MAME OPL emulator" +msgstr "Émulateur MAME OPL" + +#: sound/fmopl.cpp:53 +msgid "DOSBox OPL emulator" +msgstr "Émulateur DOSBox OPL" + +#: sound/null.h:45 +msgid "No music" +msgstr "Pas de musique" + +#: sound/softsynth/adlib.cpp:1590 +msgid "AdLib Emulator" +msgstr "Émulateur AdLib" + +#: sound/softsynth/mt32.cpp:327 +msgid "Initialising MT-32 Emulator" +msgstr "Initialisation de l'Émulateur MT-32" + +#: sound/softsynth/mt32.cpp:541 +msgid "MT-32 Emulator" +msgstr "Émulateur MT-32" + +#: sound/softsynth/pcspk.cpp:142 +msgid "PC Speaker Emulator" +msgstr "Émulateur Haut Parleur PC" + +#: sound/softsynth/pcspk.cpp:161 +msgid "IBM PCjr Emulator" +msgstr "Émulateur IBM PCjr" + +#: sound/softsynth/ym2612.cpp:762 +msgid "FM Towns Emulator" +msgstr "Émulateur FM Towns" + +#: backends/keymapper/remap-dialog.cpp:49 +msgid "Keymap:" +msgstr "Affectation des touches:" + +#: backends/keymapper/remap-dialog.cpp:66 +msgid " (Active)" +msgstr "(Actif)" + +#: backends/keymapper/remap-dialog.cpp:100 +msgid " (Global)" +msgstr "(Global)" + +#: backends/keymapper/remap-dialog.cpp:110 +msgid " (Game)" +msgstr "(Jeu)" + +#: backends/midi/windows.cpp:157 +msgid "Windows MIDI" +msgstr "MIDI Windows" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:60 +msgid "ScummVM Main Menu" +msgstr "Menu Principal ScummVM" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:66 +msgid "~L~eft handed mode" +msgstr "Mode ~G~aucher" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:67 +msgid "~I~ndy fight controls" +msgstr "Contrôle des combats d'~I~ndy" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:68 +msgid "Show mouse cursor" +msgstr "Afficher le curseur de la souris" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:69 +msgid "Snap to edges" +msgstr "Aligner sur les bords" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:71 +msgid "Touch X Offset" +msgstr "Décalage X du toucher" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:78 +msgid "Touch Y Offset" +msgstr "Décallage Y du toucher" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:90 +msgid "Use laptop trackpad-style cursor control" +msgstr "Activer le contrôle du curseur de type trackpad" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:91 +msgid "Tap for left click, double tap right click" +msgstr "Toucher pour un clic gauche, toucher deux fois pour un clic droit" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:93 +msgid "Sensitivity" +msgstr "Sensibilité" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:102 +msgid "Initial top screen scale:" +msgstr "Échelle initiale de l'écran du haut" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:108 +msgid "Main screen scaling:" +msgstr "Échelle de l'écran principal" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:110 +msgid "Hardware scale (fast, but low quality)" +msgstr "Mise à l'echelle matérielle (rapide mais qualité faible)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:111 +msgid "Software scale (good quality, but slower)" +msgstr "Mise à l'échelle logicielle (bonne qualité mais plus lent)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:112 +msgid "Unscaled (you must scroll left and right)" +msgstr "Sans changement d'échelle (vous devez faire défiler l'écran)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:114 +msgid "Brightness:" +msgstr "Luminosité:" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:124 +msgid "High quality audio (slower) (reboot)" +msgstr "Audio haute qualité (plus lent) (redémarrer)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:125 +msgid "Disable power off" +msgstr "Désactivé l'extinction" + +#: backends/platform/iphone/osys_events.cpp:339 +msgid "Touchpad mode enabled." +msgstr "Mode touchpad activé" + +#: backends/platform/iphone/osys_events.cpp:341 +msgid "Touchpad mode disabled." +msgstr "Mode touchpad désactivé" + +#: backends/platform/sdl/graphics.cpp:40 +#: backends/platform/wince/wince-sdl.cpp:111 +#: backends/platform/wince/wince-sdl.cpp:118 +msgid "Normal (no scaling)" +msgstr "Normal (échelle d'origine)" + +#: backends/platform/symbian/src/SymbianActions.cpp:41 +#: backends/platform/wince/CEActionsSmartphone.cpp:38 +msgid "Up" +msgstr "Haut" + +#: backends/platform/symbian/src/SymbianActions.cpp:42 +#: backends/platform/wince/CEActionsSmartphone.cpp:39 +msgid "Down" +msgstr "Bas" + +#: backends/platform/symbian/src/SymbianActions.cpp:43 +#: backends/platform/wince/CEActionsSmartphone.cpp:40 +msgid "Left" +msgstr "Gauche" + +#: backends/platform/symbian/src/SymbianActions.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:41 +msgid "Right" +msgstr "Droite" + +#: backends/platform/symbian/src/SymbianActions.cpp:45 +#: backends/platform/wince/CEActionsPocket.cpp:59 +#: backends/platform/wince/CEActionsSmartphone.cpp:42 +msgid "Left Click" +msgstr "Clic Gauche" + +#: backends/platform/symbian/src/SymbianActions.cpp:46 +#: backends/platform/wince/CEActionsSmartphone.cpp:43 +msgid "Right Click" +msgstr "Clic Droit" + +#: backends/platform/symbian/src/SymbianActions.cpp:49 +#: backends/platform/wince/CEActionsSmartphone.cpp:46 +msgid "Zone" +msgstr "Zone" + +#: backends/platform/symbian/src/SymbianActions.cpp:50 +#: backends/platform/wince/CEActionsPocket.cpp:53 +#: backends/platform/wince/CEActionsSmartphone.cpp:47 +msgid "Multi Function" +msgstr "Fonction Multiple" + +#: backends/platform/symbian/src/SymbianActions.cpp:51 +msgid "Swap character" +msgstr "Changement de personnage" + +#: backends/platform/symbian/src/SymbianActions.cpp:52 +msgid "Skip text" +msgstr "Sauter le texte" + +#: backends/platform/symbian/src/SymbianActions.cpp:54 +msgid "Fast mode" +msgstr "Mode rapide" + +#: backends/platform/symbian/src/SymbianActions.cpp:55 +#: backends/platform/wince/CEActionsPocket.cpp:43 +#: backends/platform/wince/CEActionsSmartphone.cpp:51 +msgid "Quit" +msgstr "Quitter" + +#: backends/platform/symbian/src/SymbianActions.cpp:56 +msgid "Debugger" +msgstr "Debugger" + +#: backends/platform/symbian/src/SymbianActions.cpp:57 +msgid "Global menu" +msgstr "Menu global" + +#: backends/platform/symbian/src/SymbianActions.cpp:58 +msgid "Virtual keyboard" +msgstr "Clavier virtuel" + +#: backends/platform/symbian/src/SymbianActions.cpp:59 +#, fuzzy +msgid "Key mapper" +msgstr "Affectation des touches" + +#: backends/platform/symbian/src/SymbianOS.cpp:446 +msgid "Do you want to quit ?" +msgstr "Voulez-vous quitter?" + +#: backends/platform/wii/options.cpp:51 +msgid "Video" +msgstr "Vidéo" + +#: backends/platform/wii/options.cpp:54 +msgid "Current video mode:" +msgstr "Mode vidéo actuel" + +#: backends/platform/wii/options.cpp:56 +#, fuzzy +msgid "Double-strike" +msgstr "Coup double" + +#: backends/platform/wii/options.cpp:60 +msgid "Horizontal underscan:" +msgstr "Underscan horizontal:" + +#: backends/platform/wii/options.cpp:66 +msgid "Vertical underscan:" +msgstr "Underscan vertical:" + +#: backends/platform/wii/options.cpp:71 +msgid "Input" +msgstr "Entrée" + +#: backends/platform/wii/options.cpp:74 +msgid "GC Pad sensitivity:" +msgstr "Sensibilité du pad GC:" + +#: backends/platform/wii/options.cpp:80 +msgid "GC Pad acceleration:" +msgstr "Acceleration du pad GC:" + +#: backends/platform/wii/options.cpp:86 +msgid "DVD" +msgstr "DVD" + +#: backends/platform/wii/options.cpp:89 backends/platform/wii/options.cpp:101 +msgid "Status:" +msgstr "Status:" + +#: backends/platform/wii/options.cpp:90 backends/platform/wii/options.cpp:102 +msgid "Unknown" +msgstr "Inconue" + +#: backends/platform/wii/options.cpp:93 +msgid "Mount DVD" +msgstr "Monter le DVD" + +#: backends/platform/wii/options.cpp:94 +msgid "Unmount DVD" +msgstr "Démonter le DVD" + +#: backends/platform/wii/options.cpp:98 +msgid "SMB" +msgstr "SMB" + +#: backends/platform/wii/options.cpp:106 +msgid "Server:" +msgstr "Serveur:" + +#: backends/platform/wii/options.cpp:110 +#, fuzzy +msgid "Share:" +msgstr "Disque partagé:" + +#: backends/platform/wii/options.cpp:114 +msgid "Username:" +msgstr "Nom d'utilisateur:" + +#: backends/platform/wii/options.cpp:118 +msgid "Password:" +msgstr "Mot de passe:" + +#: backends/platform/wii/options.cpp:121 +msgid "Init network" +msgstr "Initialiser le réseau" + +#: backends/platform/wii/options.cpp:123 +msgid "Mount SMB" +msgstr "Monter SMB" + +#: backends/platform/wii/options.cpp:124 +msgid "Unmount SMB" +msgstr "Démonter SMB" + +#: backends/platform/wii/options.cpp:145 +msgid "DVD Mounted successfully" +msgstr "DVD monté avec succès" + +#: backends/platform/wii/options.cpp:148 +msgid "Error while mounting the DVD" +msgstr "Échec du montage du DVD" + +#: backends/platform/wii/options.cpp:150 +msgid "DVD not mounted" +msgstr "DVD non monté" + +#: backends/platform/wii/options.cpp:163 +#, fuzzy +msgid "Network up, share mounted" +msgstr "Réseau connecté, disque partagé monté" + +#: backends/platform/wii/options.cpp:165 +#, fuzzy +msgid "Network up" +msgstr "Réseau connecté" + +#: backends/platform/wii/options.cpp:168 +#, fuzzy +msgid ", error while mounting the share" +msgstr ", échec du montage du disque partagé" + +#: backends/platform/wii/options.cpp:170 +#, fuzzy +msgid ", share not mounted" +msgstr ", disque partagé non monté" + +#: backends/platform/wii/options.cpp:176 +#, fuzzy +msgid "Network down" +msgstr "Réseau déconnecté" + +#: backends/platform/wii/options.cpp:180 +msgid "Initialising network" +msgstr "Initialisation du réseau" + +#: backends/platform/wii/options.cpp:184 +msgid "Timeout while initialising network" +msgstr "Dépassement du délai lors de l'initialisation du réseau" + +#: backends/platform/wii/options.cpp:188 +#, c-format +msgid "Network not initialsed (%d)" +msgstr "Réseau non initialisé (%d)" + +#: backends/platform/wince/CEActionsPocket.cpp:45 +msgid "Hide Toolbar" +msgstr "Caché la barre d'outils" + +#: backends/platform/wince/CEActionsPocket.cpp:46 +msgid "Show Keyboard" +msgstr "Afficher le clavier" + +#: backends/platform/wince/CEActionsPocket.cpp:47 +msgid "Sound on/off" +msgstr "Audio marche/arrêt" + +#: backends/platform/wince/CEActionsPocket.cpp:48 +msgid "Right click" +msgstr "Clic droit" + +#: backends/platform/wince/CEActionsPocket.cpp:49 +msgid "Show/Hide Cursor" +msgstr "Afficher/Cacher le curseur" + +#: backends/platform/wince/CEActionsPocket.cpp:50 +#, fuzzy +msgid "Free look" +msgstr "Regarder autour" + +#: backends/platform/wince/CEActionsPocket.cpp:51 +#, fuzzy +msgid "Zoom up" +msgstr "Dézoomer" + +#: backends/platform/wince/CEActionsPocket.cpp:52 +#, fuzzy +msgid "Zoom down" +msgstr "Zoomer" + +#: backends/platform/wince/CEActionsPocket.cpp:54 +#: backends/platform/wince/CEActionsSmartphone.cpp:48 +#, fuzzy +msgid "Bind Keys" +msgstr "Affecter les touches" + +#: backends/platform/wince/CEActionsPocket.cpp:55 +#, fuzzy +msgid "Cursor Up" +msgstr "Haut" + +#: backends/platform/wince/CEActionsPocket.cpp:56 +#, fuzzy +msgid "Cursor Down" +msgstr "Bas" + +#: backends/platform/wince/CEActionsPocket.cpp:57 +#, fuzzy +msgid "Cursor Left" +msgstr "Gauche" + +#: backends/platform/wince/CEActionsPocket.cpp:58 +#, fuzzy +msgid "Cursor Right" +msgstr "Droit" + +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Do you want to load or save the game?" +msgstr "Voulez-vous charger ou sauver le jeu?" + +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +msgid " Are you sure you want to quit ? " +msgstr "Voulez-vous vraiment quitter?" + +#: backends/platform/wince/CEActionsSmartphone.cpp:49 +msgid "Keyboard" +msgstr "Clavier" + +#: backends/platform/wince/CEActionsSmartphone.cpp:50 +msgid "Rotate" +msgstr "Pivoter" + +#: backends/platform/wince/CELauncherDialog.cpp:58 +msgid "Using SDL driver " +msgstr "Utilise le pilote SDL" + +#: backends/platform/wince/CELauncherDialog.cpp:62 +msgid "Display " +msgstr "Affichage" + +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "Do you want to perform an automatic scan ?" +msgstr "Voulez-vous exécuter une recherche automatique?" + +#~ msgid "Failed to load any GUI theme, aborting" +#~ msgstr "Aucun thème GUI n'a pu être chargé; abandon" + +#~ msgid "User picked target '%s' (gameid '%s')...\n" +#~ msgstr "L'utilisateur a choisi la cible '%s' (ID '%s')...\n" + +#~ msgid " Looking for a plugin supporting this gameid... " +#~ msgstr "Recherche d'un plugin supportant cet ID..." + +#~ msgid "failed\n" +#~ msgstr "Echec\n" + +#~ msgid "" +#~ "%s is an invalid gameid. Use the --list-games option to list supported " +#~ "gameid" +#~ msgstr "" +#~ "%s n'est pas un ID de jeu valide. Utilisez l'option --list-games pour " +#~ "obtenir la liste des ID reconnus" + +#~ msgid " Starting '%s'\n" +#~ msgstr "Démarrage de '%s'\n" + +#~ msgid "%s failed to instantiate engine: %s (target '%s', path '%s')" +#~ msgstr "" +#~ "Le plugin %s a échoué dans l'instanciation du moteur de jeu: %s (cible " +#~ "'%s', chemin '%s')" + +#~ msgid "Ok" +#~ msgstr "Ok" + +#~ msgid "Music driver:" +#~ msgstr "Pilote audio:" + +#~ msgid "ALSA" +#~ msgstr "ALSA" + +#~ msgid "Atari ST MIDI" +#~ msgstr "MIDI Atari ST" + +#~ msgid "SEQ" +#~ msgstr "SEQ" + +#~ msgid "DMedia" +#~ msgstr "DMedia" + +#~ msgid "CAMD" +#~ msgstr "CAMD" + +#~ msgid "CoreAudio" +#~ msgstr "CoreAudio" + +#~ msgid "CoreMIDI" +#~ msgstr "CoreMIDI" + +#~ msgid "Yamaha Pa1" +#~ msgstr "Yamaha Pa1" + +#~ msgid "Tapwave Zodiac" +#~ msgstr "Tapwave Zodiac" + +#~ msgid "FluidSynth" +#~ msgstr "FluidSynth" + +#~ msgid "AdLib" +#~ msgstr "AdLib" + +#~ msgid "IBM PCjr" +#~ msgstr "IBM PCjr" + +#~ msgid "Creative Music System" +#~ msgstr "Creative Music System" + +#~ msgid "TiMidity" +#~ msgstr "TiMidity" + +#~ msgid "About..." +#~ msgstr "A propos..." + +#~ msgid "Options..." +#~ msgstr "Options..." + +#~ msgid "Start" +#~ msgstr "Lancer" + +#~ msgid "Load..." +#~ msgstr "Charger..." + +#~ msgid "Edit Game..." +#~ msgstr "Préférence du Jeu..." + +#~ msgid "Remove Game" +#~ msgstr "Supprimer le Jeu" + +#~ msgid "Speech Only" +#~ msgstr "Audio Uniquement" + +#~ msgid "Speech and Subtitles" +#~ msgstr "Audio et Sous-titres" + +#~ msgid "Subtitles Only" +#~ msgstr "Sous-titres Uniquement" + +#~ msgid "Speech & Subs" +#~ msgstr "Parole & Sous-titres" diff --git a/po/hu_HU.po b/po/hu_HU.po new file mode 100644 index 0000000000..1d9a6c3268 --- /dev/null +++ b/po/hu_HU.po @@ -0,0 +1,1385 @@ +# LANGUAGE translation for ScummVM. +# Copyright (C) 2009 ScummVM +# This file is distributed under the same license as the ScummVM package. +# Alex Bevilacqua <alexbevi@gmail.com>, 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: ScummVM VERSION\n" +"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n" +"POT-Creation-Date: 2010-07-12 17:44+0200\n" +"PO-Revision-Date: 2009-11-25 07:42-0500\n" +"Last-Translator: Alex Bevilacqua <alexbevi@gmail.com>\n" +"Language-Team: Hungarian\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=cp1250\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: gui/about.cpp:96 +#, c-format +msgid "(built on %s)" +msgstr "" + +#: gui/about.cpp:103 +msgid "Features compiled in:" +msgstr "" + +#: gui/about.cpp:112 +msgid "Available engines:" +msgstr "" + +#: gui/browser.cpp:69 +msgid "Go up" +msgstr "" + +#: gui/browser.cpp:69 +msgid "Go to previous directory level" +msgstr "" + +#: gui/browser.cpp:70 gui/chooser.cpp:49 gui/KeysDialog.cpp:46 +#: gui/launcher.cpp:266 gui/massadd.cpp:95 gui/options.cpp:972 +#: gui/saveload.cpp:65 gui/saveload.cpp:157 gui/themebrowser.cpp:56 +#: backends/platform/wii/options.cpp:48 +msgid "Cancel" +msgstr "" + +#: gui/browser.cpp:71 gui/chooser.cpp:50 gui/themebrowser.cpp:57 +msgid "Choose" +msgstr "" + +#: gui/GuiManager.cpp:102 backends/keymapper/remap-dialog.cpp:54 +msgid "Close" +msgstr "" + +#: gui/GuiManager.cpp:105 +msgid "Mouse click" +msgstr "" + +#: gui/GuiManager.cpp:108 base/main.cpp:285 +msgid "Display keyboard" +msgstr "" + +#: gui/GuiManager.cpp:111 base/main.cpp:288 +msgid "Remap keys" +msgstr "" + +#: gui/KeysDialog.cpp:44 +msgid "Map" +msgstr "" + +#: gui/KeysDialog.cpp:45 gui/launcher.cpp:267 gui/launcher.cpp:873 +#: gui/launcher.cpp:877 gui/massadd.cpp:92 gui/options.cpp:973 +#: backends/platform/wii/options.cpp:47 +#: backends/platform/wince/CELauncherDialog.cpp:56 +msgid "OK" +msgstr "Igen" + +#: gui/KeysDialog.cpp:52 +msgid "Select an action and click 'Map'" +msgstr "" + +#: gui/KeysDialog.cpp:83 gui/KeysDialog.cpp:105 gui/KeysDialog.cpp:144 +#, c-format +msgid "Associated key : %s" +msgstr "" + +#: gui/KeysDialog.cpp:85 gui/KeysDialog.cpp:107 gui/KeysDialog.cpp:146 +#, c-format +msgid "Associated key : none" +msgstr "" + +#: gui/KeysDialog.cpp:93 +msgid "Please select an action" +msgstr "" + +#: gui/KeysDialog.cpp:109 +msgid "Press the key to associate" +msgstr "" + +#: gui/KeysDialog.cpp:148 +msgid "Choose an action to map" +msgstr "" + +#: gui/launcher.cpp:170 +msgid "Game" +msgstr "" + +#: gui/launcher.cpp:173 +msgid "ID:" +msgstr "" + +#: gui/launcher.cpp:173 gui/launcher.cpp:174 +msgid "" +"Short game identifier used for referring to savegames and running the game " +"from the command line" +msgstr "" + +#: gui/launcher.cpp:177 +msgid "Name:" +msgstr "" + +#: gui/launcher.cpp:177 gui/launcher.cpp:178 +msgid "Full title of the game" +msgstr "" + +#: gui/launcher.cpp:181 +msgid "Language:" +msgstr "" + +#: gui/launcher.cpp:181 gui/launcher.cpp:182 +msgid "" +"Language of the game. This will not turn your Spanish game version into " +"English" +msgstr "" + +#: gui/launcher.cpp:183 gui/launcher.cpp:194 gui/options.cpp:80 +#: gui/options.cpp:617 gui/options.cpp:627 gui/options.cpp:943 +#: sound/null.cpp:42 +msgid "<default>" +msgstr "<alapértelmezett>" + +#: gui/launcher.cpp:192 +msgid "Platform:" +msgstr "" + +#: gui/launcher.cpp:192 gui/launcher.cpp:193 +msgid "Platform the game was originally designed for" +msgstr "" + +#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867 +msgid "Graphics" +msgstr "Grafikával" + +#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867 +msgid "GFX" +msgstr "" + +#: gui/launcher.cpp:206 +msgid "Override global graphic settings" +msgstr "" + +#: gui/launcher.cpp:213 gui/options.cpp:873 +msgid "Audio" +msgstr "Hang" + +#: gui/launcher.cpp:215 +msgid "Override global audio settings" +msgstr "" + +#: gui/launcher.cpp:223 gui/options.cpp:877 +msgid "Volume" +msgstr "Volumene" + +#: gui/launcher.cpp:225 +msgid "Override global volume settings" +msgstr "" + +#: gui/launcher.cpp:232 gui/options.cpp:885 +msgid "MIDI" +msgstr "" + +#: gui/launcher.cpp:234 +msgid "Override global MIDI settings" +msgstr "" + +#: gui/launcher.cpp:244 gui/options.cpp:891 +msgid "Paths" +msgstr "Ösvények" + +#: gui/launcher.cpp:250 +#, fuzzy +msgid "Game Path:" +msgstr "Extra Útvonal:" + +#: gui/launcher.cpp:254 gui/options.cpp:904 +msgid "Extra Path:" +msgstr "Extra Útvonal:" + +#: gui/launcher.cpp:254 gui/launcher.cpp:255 +msgid "Specifies path to additional data used the game" +msgstr "" + +#: gui/launcher.cpp:258 +#, fuzzy +msgid "Save Path:" +msgstr "Extra Útvonal:" + +#: gui/launcher.cpp:258 gui/launcher.cpp:259 gui/options.cpp:898 +#: gui/options.cpp:899 +msgid "Specifies where your savegames are put" +msgstr "" + +#: gui/launcher.cpp:275 gui/launcher.cpp:353 gui/launcher.cpp:398 +#: gui/options.cpp:245 gui/options.cpp:400 gui/options.cpp:486 +#: gui/options.cpp:545 gui/options.cpp:706 gui/options.cpp:902 +#: gui/options.cpp:905 gui/options.cpp:909 gui/options.cpp:996 +#: gui/options.cpp:1002 gui/options.cpp:1008 gui/options.cpp:1016 +#: gui/options.cpp:1040 gui/options.cpp:1044 gui/options.cpp:1050 +#: gui/options.cpp:1057 gui/options.cpp:1156 +msgid "None" +msgstr "Semmi" + +#: gui/launcher.cpp:280 gui/launcher.cpp:357 +#: backends/platform/wii/options.cpp:56 +#, fuzzy +msgid "Default" +msgstr "<alapértelmezett>" + +#: gui/launcher.cpp:391 gui/options.cpp:1150 +msgid "Select SoundFont" +msgstr "" + +#: gui/launcher.cpp:410 gui/launcher.cpp:548 +msgid "Select directory with game data" +msgstr "" + +#: gui/launcher.cpp:428 +msgid "Select additional game directory" +msgstr "" + +#: gui/launcher.cpp:440 +msgid "Select directory for saved games" +msgstr "" + +#: gui/launcher.cpp:459 +msgid "This game ID is already taken. Please choose another one." +msgstr "" + +#: gui/launcher.cpp:500 engines/dialogs.cpp:113 +msgid "~Q~uit" +msgstr "" + +#: gui/launcher.cpp:500 +msgid "Quit ScummVM" +msgstr "" + +#: gui/launcher.cpp:501 +msgid "A~b~out..." +msgstr "" + +#: gui/launcher.cpp:501 +msgid "About ScummVM" +msgstr "" + +#: gui/launcher.cpp:502 +msgid "~O~ptions..." +msgstr "" + +#: gui/launcher.cpp:502 +msgid "Change global ScummVM options" +msgstr "" + +#: gui/launcher.cpp:504 +msgid "~S~tart" +msgstr "" + +#: gui/launcher.cpp:504 +msgid "Start selected game" +msgstr "" + +#: gui/launcher.cpp:507 +msgid "~L~oad..." +msgstr "" + +#: gui/launcher.cpp:507 +msgid "Load savegame for selected game" +msgstr "" + +#: gui/launcher.cpp:511 +msgid "~A~dd Game..." +msgstr "" + +#: gui/launcher.cpp:511 +msgid "Hold Shift for Mass Add" +msgstr "" + +#: gui/launcher.cpp:513 +msgid "~E~dit Game..." +msgstr "" + +#: gui/launcher.cpp:513 +msgid "Change game options" +msgstr "" + +#: gui/launcher.cpp:515 +msgid "~R~emove Game" +msgstr "" + +#: gui/launcher.cpp:515 +msgid "Remove game from the list. The game data files stay intact" +msgstr "" + +#: gui/launcher.cpp:522 +msgid "Search in game list" +msgstr "" + +#: gui/launcher.cpp:526 gui/launcher.cpp:1037 +msgid "Search:" +msgstr "" + +#: gui/launcher.cpp:529 gui/options.cpp:707 +msgid "Clear value" +msgstr "" + +#: gui/launcher.cpp:551 engines/dialogs.cpp:117 +msgid "Load game:" +msgstr "" + +#: gui/launcher.cpp:551 engines/dialogs.cpp:117 +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Load" +msgstr "" + +#: gui/launcher.cpp:660 +msgid "" +"Do you really want to run the mass game detector? This could potentially add " +"a huge number of games." +msgstr "" + +#: gui/launcher.cpp:661 gui/launcher.cpp:810 +#: backends/platform/symbian/src/SymbianOS.cpp:446 +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "Yes" +msgstr "" + +#: gui/launcher.cpp:661 gui/launcher.cpp:810 +#: backends/platform/symbian/src/SymbianOS.cpp:446 +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +#: backends/platform/wince/CELauncherDialog.cpp:104 +#, fuzzy +msgid "No" +msgstr "Semmi" + +#: gui/launcher.cpp:708 +msgid "ScummVM couldn't open the specified directory!" +msgstr "" + +#: gui/launcher.cpp:720 +msgid "ScummVM could not find any game in the specified directory!" +msgstr "" + +#: gui/launcher.cpp:734 +msgid "Pick the game:" +msgstr "" + +#: gui/launcher.cpp:810 +msgid "Do you really want to remove this game configuration?" +msgstr "" + +#: gui/launcher.cpp:873 +msgid "This game does not support loading games from the launcher." +msgstr "" + +#: gui/launcher.cpp:877 +msgid "ScummVM could not find any engine capable of running the selected game!" +msgstr "" + +#: gui/launcher.cpp:989 +msgid "Mass Add..." +msgstr "" + +#: gui/launcher.cpp:990 +msgid "Add Game..." +msgstr "" + +#: gui/massadd.cpp:79 gui/massadd.cpp:82 +msgid "... progress ..." +msgstr "" + +#: gui/massadd.cpp:244 +msgid "Scan complete!" +msgstr "" + +#: gui/massadd.cpp:247 +#, c-format +msgid "Discovered %d new games." +msgstr "" + +#: gui/massadd.cpp:251 +#, c-format +msgid "Scanned %d directories ..." +msgstr "" + +#: gui/massadd.cpp:254 +#, c-format +msgid "Discovered %d new games ..." +msgstr "" + +#: gui/options.cpp:78 +msgid "Never" +msgstr "Soha" + +#: gui/options.cpp:78 +msgid "every 5 mins" +msgstr "5 percenként" + +#: gui/options.cpp:78 +msgid "every 10 mins" +msgstr "10 percenként" + +#: gui/options.cpp:78 +msgid "every 15 mins" +msgstr "15 percenként" + +#: gui/options.cpp:78 +msgid "every 30 mins" +msgstr "30 percenként" + +#: gui/options.cpp:80 +msgid "8 kHz" +msgstr "" + +#: gui/options.cpp:80 +msgid "11kHz" +msgstr "" + +#: gui/options.cpp:80 +msgid "22 kHz" +msgstr "" + +#: gui/options.cpp:80 +msgid "44 kHz" +msgstr "" + +#: gui/options.cpp:80 +msgid "48 kHz" +msgstr "" + +#: gui/options.cpp:614 +msgid "Graphics mode:" +msgstr "Grafikus mód:" + +#: gui/options.cpp:625 +msgid "Render mode:" +msgstr "Renderelési mód:" + +#: gui/options.cpp:625 gui/options.cpp:626 +msgid "Special dithering modes supported by some games" +msgstr "" + +#: gui/options.cpp:635 +msgid "Fullscreen mode" +msgstr "Teljes képerny s mód:" + +#: gui/options.cpp:638 +msgid "Aspect ratio correction" +msgstr "Aspect adag korrekció" + +#: gui/options.cpp:638 +msgid "Correct aspect ratio for 320x200 games" +msgstr "" + +#: gui/options.cpp:645 +msgid "Preferred Device:" +msgstr "" + +#: gui/options.cpp:645 +#, fuzzy +msgid "Music Device:" +msgstr "Zene mennyiség:" + +#: gui/options.cpp:645 +msgid "Specifies preferred sound device or sound card emulator" +msgstr "" + +#: gui/options.cpp:645 gui/options.cpp:646 +msgid "Specifies output sound device or sound card emulator" +msgstr "" + +#: gui/options.cpp:648 +#, fuzzy +msgid "MT-32 Device:" +msgstr "Zene mennyiség:" + +#: gui/options.cpp:648 +msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output" +msgstr "" + +#: gui/options.cpp:650 +msgid "GM Device:" +msgstr "" + +#: gui/options.cpp:650 +msgid "Specifies default sound device for General MIDI output" +msgstr "" + +#: gui/options.cpp:682 +msgid "AdLib emulator:" +msgstr "AdLib vezet :" + +#: gui/options.cpp:682 gui/options.cpp:683 +msgid "AdLib is used for music in many games" +msgstr "" + +#: gui/options.cpp:693 +msgid "Output rate:" +msgstr "Kimeneti teljesítmény:" + +#: gui/options.cpp:693 gui/options.cpp:694 +msgid "" +"Higher value specifies better sound quality but may be not supported by your " +"soundcard" +msgstr "" + +#: gui/options.cpp:705 +msgid "SoundFont:" +msgstr "" + +#: gui/options.cpp:705 gui/options.cpp:706 +msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity" +msgstr "" + +#: gui/options.cpp:710 +msgid "Mixed AdLib/MIDI mode" +msgstr "Vegyes AdLib/MIDI mód" + +#: gui/options.cpp:710 +msgid "Use both MIDI and AdLib sound generation" +msgstr "" + +#: gui/options.cpp:713 +msgid "True Roland MT-32 (disable GM emulation)" +msgstr "Igaz Roland MT-32 (megbénít GM emuláció)" + +#: gui/options.cpp:713 +msgid "" +"Check if you want to use your real hardware Roland-compatible sound device " +"connected to your computer" +msgstr "" + +#: gui/options.cpp:716 +msgid "Enable Roland GS Mode" +msgstr "Képessé Roland GS Mode" + +#: gui/options.cpp:716 +msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack" +msgstr "" + +#: gui/options.cpp:719 +msgid "MIDI gain:" +msgstr "MIDI nyereség:" + +#: gui/options.cpp:732 +msgid "Text and Speech:" +msgstr "Szöveg és beszéd:" + +#: gui/options.cpp:737 gui/options.cpp:743 +#, fuzzy +msgid "Speech" +msgstr "Csak a beszéd" + +#: gui/options.cpp:738 gui/options.cpp:744 +#, fuzzy +msgid "Subtitles" +msgstr "Csak feliratok" + +#: gui/options.cpp:739 gui/options.cpp:745 +msgid "Both" +msgstr "" + +#: gui/options.cpp:743 +msgid "Spch" +msgstr "" + +#: gui/options.cpp:744 +msgid "Subs" +msgstr "" + +#: gui/options.cpp:745 +msgid "Show subtitles and play speech" +msgstr "" + +#: gui/options.cpp:749 +msgid "Subtitle speed:" +msgstr "Felirat sebesség:" + +#: gui/options.cpp:761 +msgid "Music volume:" +msgstr "Zene mennyiség:" + +#: gui/options.cpp:768 +msgid "Mute All" +msgstr "Muta Összes" + +#: gui/options.cpp:771 +msgid "SFX volume:" +msgstr "SFX mennyisége" + +#: gui/options.cpp:771 gui/options.cpp:772 +msgid "Special sound effects volume" +msgstr "" + +#: gui/options.cpp:778 +msgid "Speech volume:" +msgstr "Beszéd mennyiség:" + +#: gui/options.cpp:898 +msgid "Save Path: " +msgstr "" + +#: gui/options.cpp:901 +msgid "Theme Path:" +msgstr "" + +#: gui/options.cpp:904 gui/options.cpp:905 +msgid "Specifies path to additional data used by all games or ScummVM" +msgstr "" + +#: gui/options.cpp:908 +msgid "Plugins Path:" +msgstr "" + +#: gui/options.cpp:913 +msgid "Misc" +msgstr "" + +#: gui/options.cpp:915 +msgid "Theme:" +msgstr "Téma:" + +#: gui/options.cpp:919 +msgid "GUI Renderer:" +msgstr "Leképez eszköz GUI:" + +#: gui/options.cpp:925 +msgid "Autosave:" +msgstr "Automatikus mentés:" + +#: gui/options.cpp:933 +msgid "Keys" +msgstr "Kulcsok" + +#: gui/options.cpp:940 +msgid "GUI Language:" +msgstr "" + +#: gui/options.cpp:940 +msgid "Language of ScummVM GUI" +msgstr "" + +#: gui/options.cpp:945 +msgid "English" +msgstr "" + +#: gui/options.cpp:1089 +msgid "You have to restart ScummVM to take the effect." +msgstr "" + +#: gui/options.cpp:1102 +msgid "Select directory for savegames" +msgstr "" + +#: gui/options.cpp:1109 +msgid "The chosen directory cannot be written to. Please select another one." +msgstr "" + +#: gui/options.cpp:1118 +msgid "Select directory for GUI themes" +msgstr "" + +#: gui/options.cpp:1128 +msgid "Select directory for extra files" +msgstr "" + +#: gui/options.cpp:1139 +msgid "Select directory for plugins" +msgstr "" + +#: gui/saveload.cpp:60 gui/saveload.cpp:241 +msgid "No date saved" +msgstr "" + +#: gui/saveload.cpp:61 gui/saveload.cpp:242 +msgid "No time saved" +msgstr "" + +#: gui/saveload.cpp:62 gui/saveload.cpp:243 +msgid "No playtime saved" +msgstr "" + +#: gui/saveload.cpp:69 gui/saveload.cpp:157 +msgid "Delete" +msgstr "" + +#: gui/saveload.cpp:156 +msgid "Do you really want to delete this savegame?" +msgstr "" + +#: gui/saveload.cpp:265 +msgid "Date: " +msgstr "" + +#: gui/saveload.cpp:268 +#, fuzzy +msgid "Time: " +msgstr "Téma:" + +#: gui/saveload.cpp:273 +msgid "Playtime: " +msgstr "" + +#: gui/saveload.cpp:286 gui/saveload.cpp:353 +msgid "Untitled savestate" +msgstr "" + +#: gui/themebrowser.cpp:46 +msgid "Select a Theme" +msgstr "" + +#: gui/ThemeEngine.cpp:337 +msgid "Disabled GFX" +msgstr "" + +#: gui/ThemeEngine.cpp:338 +msgid "Standard Renderer (16bpp)" +msgstr "" + +#: gui/ThemeEngine.cpp:340 +msgid "Antialiased Renderer (16bpp)" +msgstr "" + +#: base/main.cpp:205 +#, c-format +msgid "Engine does not support debug level '%s'" +msgstr "" + +#: base/main.cpp:273 +msgid "Menu" +msgstr "" + +#: base/main.cpp:276 backends/platform/symbian/src/SymbianActions.cpp:48 +#: backends/platform/wince/CEActionsPocket.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:45 +msgid "Skip" +msgstr "" + +#: base/main.cpp:279 backends/platform/symbian/src/SymbianActions.cpp:53 +#: backends/platform/wince/CEActionsPocket.cpp:41 +#, fuzzy +msgid "Pause" +msgstr "Ösvények" + +#: base/main.cpp:282 +msgid "Skip line" +msgstr "" + +#: base/main.cpp:404 +msgid "Error running game:" +msgstr "" + +#: base/main.cpp:430 base/main.cpp:431 +msgid "Could not find any engine capable of running the selected game" +msgstr "" + +#: common/error.cpp:43 +msgid "Invalid Path" +msgstr "" + +#: common/error.cpp:44 +msgid "Game Data not found" +msgstr "" + +#: common/error.cpp:45 +msgid "Game Id not supported" +msgstr "" + +#: common/error.cpp:46 +msgid "Unsupported Color Mode" +msgstr "" + +#: common/error.cpp:48 +msgid "Read permission denied" +msgstr "" + +#: common/error.cpp:49 +msgid "Write permission denied" +msgstr "" + +#: common/error.cpp:52 +msgid "Path not exists" +msgstr "" + +#: common/error.cpp:53 +msgid "Path not a directory" +msgstr "" + +#: common/error.cpp:54 +msgid "Path not a file" +msgstr "" + +#: common/error.cpp:56 +msgid "Cannot create file" +msgstr "" + +#: common/error.cpp:57 +msgid "Reading failed" +msgstr "" + +#: common/error.cpp:58 +msgid "Writing data failed" +msgstr "" + +#: common/error.cpp:60 common/error.cpp:71 +msgid "Unknown Error" +msgstr "" + +#: common/util.cpp:254 +msgid "Hercules Green" +msgstr "" + +#: common/util.cpp:255 +msgid "Hercules Amber" +msgstr "" + +#: engines/dialogs.cpp:89 +msgid "~R~esume" +msgstr "" + +#: engines/dialogs.cpp:91 +msgid "~L~oad" +msgstr "" + +#: engines/dialogs.cpp:95 +msgid "~S~ave" +msgstr "" + +#: engines/dialogs.cpp:99 +msgid "~O~ptions" +msgstr "" + +#: engines/dialogs.cpp:104 +msgid "~H~elp" +msgstr "" + +#: engines/dialogs.cpp:107 +msgid "~A~bout" +msgstr "" + +#: engines/dialogs.cpp:109 +msgid "~R~eturn to Launcher" +msgstr "" + +#: engines/dialogs.cpp:119 +msgid "Save game:" +msgstr "" + +#: engines/dialogs.cpp:119 backends/platform/symbian/src/SymbianActions.cpp:47 +#: backends/platform/wince/CEActionsPocket.cpp:42 +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Save" +msgstr "" + +#: engines/dialogs.cpp:301 engines/mohawk/dialogs.cpp:84 +#: engines/mohawk/dialogs.cpp:118 +#, fuzzy +msgid "~O~K" +msgstr "Igen" + +#: engines/dialogs.cpp:302 engines/mohawk/dialogs.cpp:85 +#: engines/mohawk/dialogs.cpp:119 +msgid "~C~ancel" +msgstr "" + +#: engines/dialogs.cpp:305 +#, fuzzy +msgid "~K~eys" +msgstr "Kulcsok" + +#: engines/scumm/dialogs.cpp:287 +msgid "~P~revious" +msgstr "" + +#: engines/scumm/dialogs.cpp:288 +msgid "~N~ext" +msgstr "" + +#: engines/scumm/dialogs.cpp:289 +#: backends/platform/ds/arm9/source/dsoptions.cpp:59 +msgid "~C~lose" +msgstr "" + +#: engines/mohawk/dialogs.cpp:81 engines/mohawk/dialogs.cpp:115 +msgid "~Z~ip Mode Activated" +msgstr "" + +#: engines/mohawk/dialogs.cpp:82 +msgid "~T~ransitions Enabled" +msgstr "" + +#: engines/mohawk/dialogs.cpp:116 +msgid "~W~ater Effect Enabled" +msgstr "" + +#: sound/fmopl.cpp:51 +#, fuzzy +msgid "MAME OPL emulator" +msgstr "AdLib vezet :" + +#: sound/fmopl.cpp:53 +msgid "DOSBox OPL emulator" +msgstr "" + +#: sound/null.h:45 +msgid "No music" +msgstr "" + +#: sound/softsynth/adlib.cpp:1590 +#, fuzzy +msgid "AdLib Emulator" +msgstr "AdLib vezet :" + +#: sound/softsynth/mt32.cpp:327 +msgid "Initialising MT-32 Emulator" +msgstr "" + +#: sound/softsynth/mt32.cpp:541 +msgid "MT-32 Emulator" +msgstr "" + +#: sound/softsynth/pcspk.cpp:142 +msgid "PC Speaker Emulator" +msgstr "" + +#: sound/softsynth/pcspk.cpp:161 +msgid "IBM PCjr Emulator" +msgstr "" + +#: sound/softsynth/ym2612.cpp:762 +msgid "FM Towns Emulator" +msgstr "" + +#: backends/keymapper/remap-dialog.cpp:49 +msgid "Keymap:" +msgstr "" + +#: backends/keymapper/remap-dialog.cpp:66 +msgid " (Active)" +msgstr "" + +#: backends/keymapper/remap-dialog.cpp:100 +msgid " (Global)" +msgstr "" + +#: backends/keymapper/remap-dialog.cpp:110 +msgid " (Game)" +msgstr "" + +#: backends/midi/windows.cpp:157 +msgid "Windows MIDI" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:60 +msgid "ScummVM Main Menu" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:66 +#, fuzzy +msgid "~L~eft handed mode" +msgstr "Renderelési mód:" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:67 +msgid "~I~ndy fight controls" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:68 +msgid "Show mouse cursor" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:69 +msgid "Snap to edges" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:71 +msgid "Touch X Offset" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:78 +msgid "Touch Y Offset" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:90 +msgid "Use laptop trackpad-style cursor control" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:91 +msgid "Tap for left click, double tap right click" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:93 +msgid "Sensitivity" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:102 +msgid "Initial top screen scale:" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:108 +msgid "Main screen scaling:" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:110 +msgid "Hardware scale (fast, but low quality)" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:111 +msgid "Software scale (good quality, but slower)" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:112 +msgid "Unscaled (you must scroll left and right)" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:114 +msgid "Brightness:" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:124 +msgid "High quality audio (slower) (reboot)" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:125 +msgid "Disable power off" +msgstr "" + +#: backends/platform/iphone/osys_events.cpp:339 +msgid "Touchpad mode enabled." +msgstr "" + +#: backends/platform/iphone/osys_events.cpp:341 +msgid "Touchpad mode disabled." +msgstr "" + +#: backends/platform/sdl/graphics.cpp:40 +#: backends/platform/wince/wince-sdl.cpp:111 +#: backends/platform/wince/wince-sdl.cpp:118 +msgid "Normal (no scaling)" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:41 +#: backends/platform/wince/CEActionsSmartphone.cpp:38 +msgid "Up" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:42 +#: backends/platform/wince/CEActionsSmartphone.cpp:39 +msgid "Down" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:43 +#: backends/platform/wince/CEActionsSmartphone.cpp:40 +msgid "Left" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:41 +msgid "Right" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:45 +#: backends/platform/wince/CEActionsPocket.cpp:59 +#: backends/platform/wince/CEActionsSmartphone.cpp:42 +msgid "Left Click" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:46 +#: backends/platform/wince/CEActionsSmartphone.cpp:43 +msgid "Right Click" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:49 +#: backends/platform/wince/CEActionsSmartphone.cpp:46 +#, fuzzy +msgid "Zone" +msgstr "Semmi" + +#: backends/platform/symbian/src/SymbianActions.cpp:50 +#: backends/platform/wince/CEActionsPocket.cpp:53 +#: backends/platform/wince/CEActionsSmartphone.cpp:47 +msgid "Multi Function" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:51 +msgid "Swap character" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:52 +msgid "Skip text" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:54 +#, fuzzy +msgid "Fast mode" +msgstr "Grafikus mód:" + +#: backends/platform/symbian/src/SymbianActions.cpp:55 +#: backends/platform/wince/CEActionsPocket.cpp:43 +#: backends/platform/wince/CEActionsSmartphone.cpp:51 +msgid "Quit" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:56 +msgid "Debugger" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:57 +msgid "Global menu" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:58 +msgid "Virtual keyboard" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:59 +msgid "Key mapper" +msgstr "" + +#: backends/platform/symbian/src/SymbianOS.cpp:446 +msgid "Do you want to quit ?" +msgstr "" + +#: backends/platform/wii/options.cpp:51 +msgid "Video" +msgstr "" + +#: backends/platform/wii/options.cpp:54 +#, fuzzy +msgid "Current video mode:" +msgstr "Renderelési mód:" + +#: backends/platform/wii/options.cpp:56 +msgid "Double-strike" +msgstr "" + +#: backends/platform/wii/options.cpp:60 +msgid "Horizontal underscan:" +msgstr "" + +#: backends/platform/wii/options.cpp:66 +msgid "Vertical underscan:" +msgstr "" + +#: backends/platform/wii/options.cpp:71 +msgid "Input" +msgstr "" + +#: backends/platform/wii/options.cpp:74 +msgid "GC Pad sensitivity:" +msgstr "" + +#: backends/platform/wii/options.cpp:80 +msgid "GC Pad acceleration:" +msgstr "" + +#: backends/platform/wii/options.cpp:86 +msgid "DVD" +msgstr "" + +#: backends/platform/wii/options.cpp:89 backends/platform/wii/options.cpp:101 +msgid "Status:" +msgstr "" + +#: backends/platform/wii/options.cpp:90 backends/platform/wii/options.cpp:102 +msgid "Unknown" +msgstr "" + +#: backends/platform/wii/options.cpp:93 +msgid "Mount DVD" +msgstr "" + +#: backends/platform/wii/options.cpp:94 +msgid "Unmount DVD" +msgstr "" + +#: backends/platform/wii/options.cpp:98 +msgid "SMB" +msgstr "" + +#: backends/platform/wii/options.cpp:106 +#, fuzzy +msgid "Server:" +msgstr "Soha" + +#: backends/platform/wii/options.cpp:110 +msgid "Share:" +msgstr "" + +#: backends/platform/wii/options.cpp:114 +msgid "Username:" +msgstr "" + +#: backends/platform/wii/options.cpp:118 +msgid "Password:" +msgstr "" + +#: backends/platform/wii/options.cpp:121 +msgid "Init network" +msgstr "" + +#: backends/platform/wii/options.cpp:123 +msgid "Mount SMB" +msgstr "" + +#: backends/platform/wii/options.cpp:124 +msgid "Unmount SMB" +msgstr "" + +#: backends/platform/wii/options.cpp:145 +msgid "DVD Mounted successfully" +msgstr "" + +#: backends/platform/wii/options.cpp:148 +msgid "Error while mounting the DVD" +msgstr "" + +#: backends/platform/wii/options.cpp:150 +msgid "DVD not mounted" +msgstr "" + +#: backends/platform/wii/options.cpp:163 +msgid "Network up, share mounted" +msgstr "" + +#: backends/platform/wii/options.cpp:165 +msgid "Network up" +msgstr "" + +#: backends/platform/wii/options.cpp:168 +msgid ", error while mounting the share" +msgstr "" + +#: backends/platform/wii/options.cpp:170 +msgid ", share not mounted" +msgstr "" + +#: backends/platform/wii/options.cpp:176 +msgid "Network down" +msgstr "" + +#: backends/platform/wii/options.cpp:180 +msgid "Initialising network" +msgstr "" + +#: backends/platform/wii/options.cpp:184 +msgid "Timeout while initialising network" +msgstr "" + +#: backends/platform/wii/options.cpp:188 +#, c-format +msgid "Network not initialsed (%d)" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:45 +msgid "Hide Toolbar" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:46 +msgid "Show Keyboard" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:47 +msgid "Sound on/off" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:48 +msgid "Right click" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:49 +msgid "Show/Hide Cursor" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:50 +msgid "Free look" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:51 +msgid "Zoom up" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:52 +msgid "Zoom down" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:54 +#: backends/platform/wince/CEActionsSmartphone.cpp:48 +#, fuzzy +msgid "Bind Keys" +msgstr "Kulcsok" + +#: backends/platform/wince/CEActionsPocket.cpp:55 +msgid "Cursor Up" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:56 +msgid "Cursor Down" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:57 +msgid "Cursor Left" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:58 +msgid "Cursor Right" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Do you want to load or save the game?" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +msgid " Are you sure you want to quit ? " +msgstr "" + +#: backends/platform/wince/CEActionsSmartphone.cpp:49 +msgid "Keyboard" +msgstr "" + +#: backends/platform/wince/CEActionsSmartphone.cpp:50 +msgid "Rotate" +msgstr "" + +#: backends/platform/wince/CELauncherDialog.cpp:58 +#, fuzzy +msgid "Using SDL driver " +msgstr "Zenei vezet :" + +#: backends/platform/wince/CELauncherDialog.cpp:62 +msgid "Display " +msgstr "" + +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "Do you want to perform an automatic scan ?" +msgstr "" + +#~ msgid "Music driver:" +#~ msgstr "Zenei vezet :" + +#, fuzzy +#~ msgid "CoreAudio" +#~ msgstr "Hang" + +#, fuzzy +#~ msgid "AdLib" +#~ msgstr "Hang" + +#~ msgid "Speech Only" +#~ msgstr "Csak a beszéd" + +#~ msgid "Speech and Subtitles" +#~ msgstr "Beszéd és a Feliratok" + +#~ msgid "Subtitles Only" +#~ msgstr "Csak feliratok" + +#~ msgid "Speech & Subs" +#~ msgstr "Beszéd s Feliratok" diff --git a/po/it_IT.po b/po/it_IT.po new file mode 100644 index 0000000000..bbe6e92e95 --- /dev/null +++ b/po/it_IT.po @@ -0,0 +1,1362 @@ +# LANGUAGE translation for ScummVM. +# Copyright (C) YEAR ScummVM Team +# This file is distributed under the same license as the ScummVM package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: ScummVM 1.2.0svn\n" +"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n" +"POT-Creation-Date: 2010-07-12 17:44+0200\n" +"PO-Revision-Date: 2010-06-30 23:56+0100\n" +"Last-Translator: Maff <matteo.maff at gmail dot com>\n" +"Language-Team: Italian\n" +"Language: Italiano\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" + +#: gui/about.cpp:96 +#, c-format +msgid "(built on %s)" +msgstr "(build creata il %s)" + +#: gui/about.cpp:103 +msgid "Features compiled in:" +msgstr "Funzionalità compilate in:" + +#: gui/about.cpp:112 +msgid "Available engines:" +msgstr "Motori disponibili:" + +#: gui/browser.cpp:69 +msgid "Go up" +msgstr "Cartella superiore" + +#: gui/browser.cpp:69 +msgid "Go to previous directory level" +msgstr "Vai alla cartella superiore" + +#: gui/browser.cpp:70 gui/chooser.cpp:49 gui/KeysDialog.cpp:46 +#: gui/launcher.cpp:266 gui/massadd.cpp:95 gui/options.cpp:972 +#: gui/saveload.cpp:65 gui/saveload.cpp:157 gui/themebrowser.cpp:56 +#: backends/platform/wii/options.cpp:48 +msgid "Cancel" +msgstr "Annulla" + +#: gui/browser.cpp:71 gui/chooser.cpp:50 gui/themebrowser.cpp:57 +msgid "Choose" +msgstr "Scegli" + +#: gui/GuiManager.cpp:102 backends/keymapper/remap-dialog.cpp:54 +msgid "Close" +msgstr "Chiudi" + +#: gui/GuiManager.cpp:105 +msgid "Mouse click" +msgstr "Clic del mouse" + +#: gui/GuiManager.cpp:108 base/main.cpp:285 +msgid "Display keyboard" +msgstr "Mostra tastiera" + +#: gui/GuiManager.cpp:111 base/main.cpp:288 +msgid "Remap keys" +msgstr "Riprogramma tasti" + +#: gui/KeysDialog.cpp:44 +msgid "Map" +msgstr "Mappa" + +#: gui/KeysDialog.cpp:45 gui/launcher.cpp:267 gui/launcher.cpp:873 +#: gui/launcher.cpp:877 gui/massadd.cpp:92 gui/options.cpp:973 +#: backends/platform/wii/options.cpp:47 +#: backends/platform/wince/CELauncherDialog.cpp:56 +msgid "OK" +msgstr "OK" + +#: gui/KeysDialog.cpp:52 +msgid "Select an action and click 'Map'" +msgstr "Seleziona un'azione e clicca 'Mappa'" + +#: gui/KeysDialog.cpp:83 gui/KeysDialog.cpp:105 gui/KeysDialog.cpp:144 +#, c-format +msgid "Associated key : %s" +msgstr "Tasto associato: %s" + +#: gui/KeysDialog.cpp:85 gui/KeysDialog.cpp:107 gui/KeysDialog.cpp:146 +#, c-format +msgid "Associated key : none" +msgstr "Tasto associato: nessuno" + +#: gui/KeysDialog.cpp:93 +msgid "Please select an action" +msgstr "Seleziona un'azione" + +#: gui/KeysDialog.cpp:109 +msgid "Press the key to associate" +msgstr "Premi il tasto da associare" + +#: gui/KeysDialog.cpp:148 +msgid "Choose an action to map" +msgstr "Scegli un'azione da mappare" + +#: gui/launcher.cpp:170 +msgid "Game" +msgstr "Gioco" + +#: gui/launcher.cpp:173 +msgid "ID:" +msgstr "ID:" + +#: gui/launcher.cpp:173 gui/launcher.cpp:174 +msgid "" +"Short game identifier used for referring to savegames and running the game " +"from the command line" +msgstr "" +"Breve identificatore di gioco utilizzato per il riferimento a salvataggi e " +"per l'esecuzione del gioco dalla riga di comando" + +#: gui/launcher.cpp:177 +msgid "Name:" +msgstr "Nome:" + +#: gui/launcher.cpp:177 gui/launcher.cpp:178 +msgid "Full title of the game" +msgstr "Titolo completo del gioco" + +#: gui/launcher.cpp:181 +msgid "Language:" +msgstr "Lingua:" + +#: gui/launcher.cpp:181 gui/launcher.cpp:182 +msgid "" +"Language of the game. This will not turn your Spanish game version into " +"English" +msgstr "" +"Lingua del gioco. Un gioco inglese non potrà risultare tradotto in italiano" + +#: gui/launcher.cpp:183 gui/launcher.cpp:194 gui/options.cpp:80 +#: gui/options.cpp:617 gui/options.cpp:627 gui/options.cpp:943 +#: sound/null.cpp:42 +msgid "<default>" +msgstr "<predefinito>" + +#: gui/launcher.cpp:192 +msgid "Platform:" +msgstr "Piattaforma:" + +#: gui/launcher.cpp:192 gui/launcher.cpp:193 +msgid "Platform the game was originally designed for" +msgstr "La piattaforma per la quale il gioco è stato concepito" + +#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867 +msgid "Graphics" +msgstr "Grafica" + +#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867 +msgid "GFX" +msgstr "Grafica" + +#: gui/launcher.cpp:206 +msgid "Override global graphic settings" +msgstr "Ignora le impostazioni grafiche globali" + +#: gui/launcher.cpp:213 gui/options.cpp:873 +msgid "Audio" +msgstr "Audio" + +#: gui/launcher.cpp:215 +msgid "Override global audio settings" +msgstr "Ignora le impostazioni audio globali" + +#: gui/launcher.cpp:223 gui/options.cpp:877 +msgid "Volume" +msgstr "Volume" + +#: gui/launcher.cpp:225 +msgid "Override global volume settings" +msgstr "Ignora le impostazioni globali di volume" + +#: gui/launcher.cpp:232 gui/options.cpp:885 +msgid "MIDI" +msgstr "MIDI" + +#: gui/launcher.cpp:234 +msgid "Override global MIDI settings" +msgstr "Ignora le impostazioni MIDI globali" + +#: gui/launcher.cpp:244 gui/options.cpp:891 +msgid "Paths" +msgstr "Percorsi" + +#: gui/launcher.cpp:250 +msgid "Game Path:" +msgstr "Percorso gioco:" + +#: gui/launcher.cpp:254 gui/options.cpp:904 +msgid "Extra Path:" +msgstr "Percorso extra:" + +#: gui/launcher.cpp:254 gui/launcher.cpp:255 +msgid "Specifies path to additional data used the game" +msgstr "Specifica il percorso di ulteriori dati usati dal gioco" + +#: gui/launcher.cpp:258 +msgid "Save Path:" +msgstr "Salvataggi:" + +#: gui/launcher.cpp:258 gui/launcher.cpp:259 gui/options.cpp:898 +#: gui/options.cpp:899 +msgid "Specifies where your savegames are put" +msgstr "Specifica dove archiviare i salvataggi" + +#: gui/launcher.cpp:275 gui/launcher.cpp:353 gui/launcher.cpp:398 +#: gui/options.cpp:245 gui/options.cpp:400 gui/options.cpp:486 +#: gui/options.cpp:545 gui/options.cpp:706 gui/options.cpp:902 +#: gui/options.cpp:905 gui/options.cpp:909 gui/options.cpp:996 +#: gui/options.cpp:1002 gui/options.cpp:1008 gui/options.cpp:1016 +#: gui/options.cpp:1040 gui/options.cpp:1044 gui/options.cpp:1050 +#: gui/options.cpp:1057 gui/options.cpp:1156 +msgid "None" +msgstr "Nessuno" + +#: gui/launcher.cpp:280 gui/launcher.cpp:357 +#: backends/platform/wii/options.cpp:56 +msgid "Default" +msgstr "Predefinito" + +#: gui/launcher.cpp:391 gui/options.cpp:1150 +msgid "Select SoundFont" +msgstr "Seleziona SoundFont" + +#: gui/launcher.cpp:410 gui/launcher.cpp:548 +msgid "Select directory with game data" +msgstr "Seleziona la cartella contenente i file di gioco" + +#: gui/launcher.cpp:428 +msgid "Select additional game directory" +msgstr "Seleziona la cartella di gioco aggiuntiva" + +#: gui/launcher.cpp:440 +msgid "Select directory for saved games" +msgstr "Seleziona la cartella dei salvataggi" + +#: gui/launcher.cpp:459 +msgid "This game ID is already taken. Please choose another one." +msgstr "Questo ID di gioco è già in uso. Si prega di sceglierne un'altro." + +#: gui/launcher.cpp:500 engines/dialogs.cpp:113 +msgid "~Q~uit" +msgstr "C~h~iudi" + +#: gui/launcher.cpp:500 +msgid "Quit ScummVM" +msgstr "Chiudi ScummVM" + +#: gui/launcher.cpp:501 +msgid "A~b~out..." +msgstr "~I~nfo..." + +#: gui/launcher.cpp:501 +msgid "About ScummVM" +msgstr "Informazioni su ScummVM" + +#: gui/launcher.cpp:502 +msgid "~O~ptions..." +msgstr "~O~pzioni..." + +#: gui/launcher.cpp:502 +msgid "Change global ScummVM options" +msgstr "Modifica le opzioni globali di ScummVM" + +#: gui/launcher.cpp:504 +msgid "~S~tart" +msgstr "~G~ioca" + +#: gui/launcher.cpp:504 +msgid "Start selected game" +msgstr "Esegue il gioco selezionato" + +#: gui/launcher.cpp:507 +msgid "~L~oad..." +msgstr "~C~arica..." + +#: gui/launcher.cpp:507 +msgid "Load savegame for selected game" +msgstr "Carica un salvataggio del gioco selezionato" + +#: gui/launcher.cpp:511 +msgid "~A~dd Game..." +msgstr "~A~ggiungi gioco..." + +#: gui/launcher.cpp:511 +msgid "Hold Shift for Mass Add" +msgstr "Tieni premuto Shift per l'aggiunta in massa" + +#: gui/launcher.cpp:513 +msgid "~E~dit Game..." +msgstr "~M~odifica gioco..." + +#: gui/launcher.cpp:513 +msgid "Change game options" +msgstr "Modifica le opzioni di gioco" + +#: gui/launcher.cpp:515 +msgid "~R~emove Game" +msgstr "~R~imuovi gioco" + +#: gui/launcher.cpp:515 +msgid "Remove game from the list. The game data files stay intact" +msgstr "Rimuove il gioco dalla lista. I file del gioco rimarranno intatti" + +#: gui/launcher.cpp:522 +msgid "Search in game list" +msgstr "Cerca nella lista dei giochi" + +#: gui/launcher.cpp:526 gui/launcher.cpp:1037 +msgid "Search:" +msgstr "Cerca:" + +#: gui/launcher.cpp:529 gui/options.cpp:707 +msgid "Clear value" +msgstr "Cancella" + +#: gui/launcher.cpp:551 engines/dialogs.cpp:117 +msgid "Load game:" +msgstr "Carica gioco:" + +#: gui/launcher.cpp:551 engines/dialogs.cpp:117 +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Load" +msgstr "Carica" + +#: gui/launcher.cpp:660 +msgid "" +"Do you really want to run the mass game detector? This could potentially add " +"a huge number of games." +msgstr "" +"Vuoi davvero eseguire il rilevatore di giochi in massa? Potrebbe aggiungere " +"un numero enorme di giochi." + +#: gui/launcher.cpp:661 gui/launcher.cpp:810 +#: backends/platform/symbian/src/SymbianOS.cpp:446 +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "Yes" +msgstr "Sì" + +#: gui/launcher.cpp:661 gui/launcher.cpp:810 +#: backends/platform/symbian/src/SymbianOS.cpp:446 +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "No" +msgstr "No" + +#: gui/launcher.cpp:708 +msgid "ScummVM couldn't open the specified directory!" +msgstr "ScummVM non ha potuto aprire la cartella specificata!" + +#: gui/launcher.cpp:720 +msgid "ScummVM could not find any game in the specified directory!" +msgstr "ScummVM non ha potuto trovare nessun gioco nella cartella specificata!" + +#: gui/launcher.cpp:734 +msgid "Pick the game:" +msgstr "Scegli il gioco:" + +#: gui/launcher.cpp:810 +msgid "Do you really want to remove this game configuration?" +msgstr "Sei sicuro di voler rimuovere questa configurazione di gioco?" + +#: gui/launcher.cpp:873 +msgid "This game does not support loading games from the launcher." +msgstr "" +"Questo gioco non supporta il caricamento di salvataggi dalla schermata di " +"avvio." + +#: gui/launcher.cpp:877 +msgid "ScummVM could not find any engine capable of running the selected game!" +msgstr "" +"ScummVM non ha potuto trovare un motore in grado di eseguire il gioco " +"selezionato!" + +#: gui/launcher.cpp:989 +msgid "Mass Add..." +msgstr "Agg. in massa..." + +#: gui/launcher.cpp:990 +msgid "Add Game..." +msgstr "Aggiungi gioco..." + +#: gui/massadd.cpp:79 gui/massadd.cpp:82 +msgid "... progress ..." +msgstr "... progresso ..." + +#: gui/massadd.cpp:244 +msgid "Scan complete!" +msgstr "Scansione completa!" + +#: gui/massadd.cpp:247 +#, c-format +msgid "Discovered %d new games." +msgstr "Rilevati %d nuovi giochi." + +#: gui/massadd.cpp:251 +#, c-format +msgid "Scanned %d directories ..." +msgstr "%d cartelle analizzate..." + +#: gui/massadd.cpp:254 +#, c-format +msgid "Discovered %d new games ..." +msgstr "Rilevati %d nuovi giochi..." + +#: gui/options.cpp:78 +msgid "Never" +msgstr "Mai" + +#: gui/options.cpp:78 +msgid "every 5 mins" +msgstr "ogni 5 minuti" + +#: gui/options.cpp:78 +msgid "every 10 mins" +msgstr "ogni 10 minuti" + +#: gui/options.cpp:78 +msgid "every 15 mins" +msgstr "ogni 15 minuti" + +#: gui/options.cpp:78 +msgid "every 30 mins" +msgstr "ogni 30 minuti" + +#: gui/options.cpp:80 +msgid "8 kHz" +msgstr "8 kHz" + +#: gui/options.cpp:80 +msgid "11kHz" +msgstr "11kHz" + +#: gui/options.cpp:80 +msgid "22 kHz" +msgstr "22 kHz" + +#: gui/options.cpp:80 +msgid "44 kHz" +msgstr "44 kHz" + +#: gui/options.cpp:80 +msgid "48 kHz" +msgstr "48 kHz" + +#: gui/options.cpp:614 +msgid "Graphics mode:" +msgstr "Modalità:" + +#: gui/options.cpp:625 +msgid "Render mode:" +msgstr "Resa grafica:" + +#: gui/options.cpp:625 gui/options.cpp:626 +msgid "Special dithering modes supported by some games" +msgstr "Modalità di resa grafica speciali supportate da alcuni giochi" + +#: gui/options.cpp:635 +msgid "Fullscreen mode" +msgstr "Modalità a schermo intero" + +#: gui/options.cpp:638 +msgid "Aspect ratio correction" +msgstr "Correzione proporzioni" + +#: gui/options.cpp:638 +msgid "Correct aspect ratio for 320x200 games" +msgstr "Corregge le proporzioni dei giochi 320x200" + +#: gui/options.cpp:645 +msgid "Preferred Device:" +msgstr "Disp. preferito:" + +#: gui/options.cpp:645 +#, fuzzy +msgid "Music Device:" +msgstr "Dispositivo GM:" + +#: gui/options.cpp:645 +msgid "Specifies preferred sound device or sound card emulator" +msgstr "" +"Specifica il dispositivo audio o l'emulatore della scheda audio preferiti" + +#: gui/options.cpp:645 gui/options.cpp:646 +msgid "Specifies output sound device or sound card emulator" +msgstr "" +"Specifica il dispositivo di output audio o l'emulatore della scheda audio" + +#: gui/options.cpp:648 +#, fuzzy +msgid "MT-32 Device:" +msgstr "Disposit. MT32:" + +#: gui/options.cpp:648 +msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output" +msgstr "" +"Specifica il dispositivo audio predefinito per l'output Roland MT-32/LAPC1/" +"CM32l/CM64" + +#: gui/options.cpp:650 +msgid "GM Device:" +msgstr "Dispositivo GM:" + +#: gui/options.cpp:650 +msgid "Specifies default sound device for General MIDI output" +msgstr "Specifica il dispositivo audio predefinito per l'output General MIDI" + +#: gui/options.cpp:682 +msgid "AdLib emulator:" +msgstr "Emulatore AdLib:" + +#: gui/options.cpp:682 gui/options.cpp:683 +msgid "AdLib is used for music in many games" +msgstr "AdLib è utilizzato per la musica in molti giochi" + +#: gui/options.cpp:693 +msgid "Output rate:" +msgstr "Frequenza:" + +#: gui/options.cpp:693 gui/options.cpp:694 +msgid "" +"Higher value specifies better sound quality but may be not supported by your " +"soundcard" +msgstr "" +"Valori più alti restituiscono un suono di maggior qualità, ma potrebbero non " +"essere supportati dalla tua scheda audio" + +#: gui/options.cpp:705 +msgid "SoundFont:" +msgstr "SoundFont:" + +#: gui/options.cpp:705 gui/options.cpp:706 +msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity" +msgstr "SoundFont è supportato da alcune schede audio, Fluidsynth e Timidity" + +#: gui/options.cpp:710 +msgid "Mixed AdLib/MIDI mode" +msgstr "Modalità mista AdLib/MIDI" + +#: gui/options.cpp:710 +msgid "Use both MIDI and AdLib sound generation" +msgstr "Utilizza generazione di suono sia MIDI che AdLib" + +#: gui/options.cpp:713 +msgid "True Roland MT-32 (disable GM emulation)" +msgstr "Roland MT-32 effettivo (disattiva emulazione GM)" + +#: gui/options.cpp:713 +msgid "" +"Check if you want to use your real hardware Roland-compatible sound device " +"connected to your computer" +msgstr "" +"Seleziona se vuoi usare il dispositivo hardware audio compatibile con Roland " +"che è connesso al tuo computer" + +#: gui/options.cpp:716 +msgid "Enable Roland GS Mode" +msgstr "Attiva la modalità Roland GS" + +#: gui/options.cpp:716 +msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack" +msgstr "" +"Disattiva la mappatura General MIDI per i giochi con colonna sonora Roland " +"MT-32" + +#: gui/options.cpp:719 +msgid "MIDI gain:" +msgstr "Guadagno MIDI:" + +#: gui/options.cpp:732 +msgid "Text and Speech:" +msgstr "Testo e voci:" + +#: gui/options.cpp:737 gui/options.cpp:743 +msgid "Speech" +msgstr "Voci" + +#: gui/options.cpp:738 gui/options.cpp:744 +msgid "Subtitles" +msgstr "Sottotitoli" + +#: gui/options.cpp:739 gui/options.cpp:745 +msgid "Both" +msgstr "Entrambi" + +#: gui/options.cpp:743 +msgid "Spch" +msgstr "Voci" + +#: gui/options.cpp:744 +msgid "Subs" +msgstr "Sub" + +#: gui/options.cpp:745 +msgid "Show subtitles and play speech" +msgstr "Mostra i sottotitoli e attiva le voci" + +#: gui/options.cpp:749 +msgid "Subtitle speed:" +msgstr "Velocità testo:" + +#: gui/options.cpp:761 +msgid "Music volume:" +msgstr "Volume musica:" + +#: gui/options.cpp:768 +msgid "Mute All" +msgstr "Disattiva audio" + +#: gui/options.cpp:771 +msgid "SFX volume:" +msgstr "Volume effetti:" + +#: gui/options.cpp:771 gui/options.cpp:772 +msgid "Special sound effects volume" +msgstr "Volume degli effetti sonori" + +#: gui/options.cpp:778 +msgid "Speech volume:" +msgstr "Volume voci:" + +#: gui/options.cpp:898 +msgid "Save Path: " +msgstr "Salvataggi:" + +#: gui/options.cpp:901 +msgid "Theme Path:" +msgstr "Percorso tema:" + +#: gui/options.cpp:904 gui/options.cpp:905 +msgid "Specifies path to additional data used by all games or ScummVM" +msgstr "Specifica il percorso di ulteriori dati usati dai giochi o da ScummVM" + +#: gui/options.cpp:908 +msgid "Plugins Path:" +msgstr "Percorso plugin:" + +#: gui/options.cpp:913 +msgid "Misc" +msgstr "Varie" + +#: gui/options.cpp:915 +msgid "Theme:" +msgstr "Tema:" + +#: gui/options.cpp:919 +msgid "GUI Renderer:" +msgstr "Renderer GUI:" + +#: gui/options.cpp:925 +msgid "Autosave:" +msgstr "Autosalva:" + +#: gui/options.cpp:933 +msgid "Keys" +msgstr "Tasti" + +#: gui/options.cpp:940 +msgid "GUI Language:" +msgstr "Lingua GUI:" + +#: gui/options.cpp:940 +msgid "Language of ScummVM GUI" +msgstr "Lingua dell'interfaccia grafica di ScummVM" + +#: gui/options.cpp:945 +msgid "English" +msgstr "Inglese" + +#: gui/options.cpp:1089 +msgid "You have to restart ScummVM to take the effect." +msgstr "Devi riavviare ScummVM affinché le modifiche abbiano effetto." + +#: gui/options.cpp:1102 +msgid "Select directory for savegames" +msgstr "Seleziona la cartella per i salvataggi" + +#: gui/options.cpp:1109 +msgid "The chosen directory cannot be written to. Please select another one." +msgstr "La cartella scelta è in sola lettura. Si prega di sceglierne un'altra." + +#: gui/options.cpp:1118 +msgid "Select directory for GUI themes" +msgstr "Seleziona la cartella dei temi dell'interfaccia" + +#: gui/options.cpp:1128 +msgid "Select directory for extra files" +msgstr "Seleziona la cartella dei file aggiuntivi" + +#: gui/options.cpp:1139 +msgid "Select directory for plugins" +msgstr "Seleziona la cartella dei plugin" + +#: gui/saveload.cpp:60 gui/saveload.cpp:241 +msgid "No date saved" +msgstr "Nessuna data salvata" + +#: gui/saveload.cpp:61 gui/saveload.cpp:242 +msgid "No time saved" +msgstr "Nessun orario salvato" + +#: gui/saveload.cpp:62 gui/saveload.cpp:243 +msgid "No playtime saved" +msgstr "Nessun tempo salvato" + +#: gui/saveload.cpp:69 gui/saveload.cpp:157 +msgid "Delete" +msgstr "Elimina" + +#: gui/saveload.cpp:156 +msgid "Do you really want to delete this savegame?" +msgstr "Sei sicuro di voler eliminare questo salvataggio?" + +#: gui/saveload.cpp:265 +msgid "Date: " +msgstr "Data: " + +#: gui/saveload.cpp:268 +msgid "Time: " +msgstr "Ora: " + +#: gui/saveload.cpp:273 +msgid "Playtime: " +msgstr "Tempo di gioco: " + +#: gui/saveload.cpp:286 gui/saveload.cpp:353 +msgid "Untitled savestate" +msgstr "Salvataggio senza titolo" + +#: gui/themebrowser.cpp:46 +msgid "Select a Theme" +msgstr "Seleziona un tema" + +#: gui/ThemeEngine.cpp:337 +msgid "Disabled GFX" +msgstr "Grafica disattivata" + +#: gui/ThemeEngine.cpp:338 +msgid "Standard Renderer (16bpp)" +msgstr "Renderer standard (16bpp)" + +#: gui/ThemeEngine.cpp:340 +msgid "Antialiased Renderer (16bpp)" +msgstr "Renderer con antialiasing (16bpp)" + +#: base/main.cpp:205 +#, c-format +msgid "Engine does not support debug level '%s'" +msgstr "Il motore non supporta il livello di debug '%s'" + +#: base/main.cpp:273 +msgid "Menu" +msgstr "Menu" + +#: base/main.cpp:276 backends/platform/symbian/src/SymbianActions.cpp:48 +#: backends/platform/wince/CEActionsPocket.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:45 +msgid "Skip" +msgstr "Salta" + +#: base/main.cpp:279 backends/platform/symbian/src/SymbianActions.cpp:53 +#: backends/platform/wince/CEActionsPocket.cpp:41 +msgid "Pause" +msgstr "Pausa" + +#: base/main.cpp:282 +msgid "Skip line" +msgstr "Salta battuta" + +#: base/main.cpp:404 +msgid "Error running game:" +msgstr "Errore nell'esecuzione del gioco:" + +#: base/main.cpp:430 base/main.cpp:431 +msgid "Could not find any engine capable of running the selected game" +msgstr "" +"Impossibile trovare un motore in grado di eseguire il gioco selezionato" + +#: common/error.cpp:43 +msgid "Invalid Path" +msgstr "Percorso non valido" + +#: common/error.cpp:44 +msgid "Game Data not found" +msgstr "Dati di gioco non trovati" + +#: common/error.cpp:45 +msgid "Game Id not supported" +msgstr "ID di gioco non supportato" + +#: common/error.cpp:46 +msgid "Unsupported Color Mode" +msgstr "Modalità colore non supportata" + +#: common/error.cpp:48 +msgid "Read permission denied" +msgstr "Autorizzazione di lettura negata" + +#: common/error.cpp:49 +msgid "Write permission denied" +msgstr "Autorizzazione di scrittura negata" + +#: common/error.cpp:52 +msgid "Path not exists" +msgstr "Il percorso non esiste" + +#: common/error.cpp:53 +msgid "Path not a directory" +msgstr "Il percorso non è una cartella" + +#: common/error.cpp:54 +msgid "Path not a file" +msgstr "Il percorso non è un file" + +#: common/error.cpp:56 +msgid "Cannot create file" +msgstr "Impossibile creare il file" + +#: common/error.cpp:57 +msgid "Reading failed" +msgstr "Lettura fallita" + +#: common/error.cpp:58 +msgid "Writing data failed" +msgstr "Scrittura dati fallita" + +#: common/error.cpp:60 common/error.cpp:71 +msgid "Unknown Error" +msgstr "Errore sconosciuto" + +#: common/util.cpp:254 +msgid "Hercules Green" +msgstr "Hercules verde" + +#: common/util.cpp:255 +msgid "Hercules Amber" +msgstr "Hercules ambra" + +#: engines/dialogs.cpp:89 +msgid "~R~esume" +msgstr "~R~ipristina" + +#: engines/dialogs.cpp:91 +msgid "~L~oad" +msgstr "~C~arica" + +#: engines/dialogs.cpp:95 +msgid "~S~ave" +msgstr "~S~alva" + +#: engines/dialogs.cpp:99 +msgid "~O~ptions" +msgstr "~O~pzioni" + +#: engines/dialogs.cpp:104 +msgid "~H~elp" +msgstr "~A~iuto" + +#: engines/dialogs.cpp:107 +msgid "~A~bout" +msgstr "~I~nfo" + +#: engines/dialogs.cpp:109 +msgid "~R~eturn to Launcher" +msgstr "~V~ai a schermata di avvio" + +#: engines/dialogs.cpp:119 +msgid "Save game:" +msgstr "Salva gioco:" + +#: engines/dialogs.cpp:119 backends/platform/symbian/src/SymbianActions.cpp:47 +#: backends/platform/wince/CEActionsPocket.cpp:42 +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Save" +msgstr "Salva" + +#: engines/dialogs.cpp:301 engines/mohawk/dialogs.cpp:84 +#: engines/mohawk/dialogs.cpp:118 +msgid "~O~K" +msgstr "~O~K" + +#: engines/dialogs.cpp:302 engines/mohawk/dialogs.cpp:85 +#: engines/mohawk/dialogs.cpp:119 +msgid "~C~ancel" +msgstr "~A~nnulla" + +#: engines/dialogs.cpp:305 +msgid "~K~eys" +msgstr "~T~asti" + +#: engines/scumm/dialogs.cpp:287 +msgid "~P~revious" +msgstr "~P~recedenti" + +#: engines/scumm/dialogs.cpp:288 +msgid "~N~ext" +msgstr "~S~uccessivi" + +#: engines/scumm/dialogs.cpp:289 +#: backends/platform/ds/arm9/source/dsoptions.cpp:59 +msgid "~C~lose" +msgstr "~C~hiudi" + +#: engines/mohawk/dialogs.cpp:81 engines/mohawk/dialogs.cpp:115 +msgid "~Z~ip Mode Activated" +msgstr "Modalità ~Z~ip attivata" + +#: engines/mohawk/dialogs.cpp:82 +msgid "~T~ransitions Enabled" +msgstr "~T~ransizioni attive" + +#: engines/mohawk/dialogs.cpp:116 +msgid "~W~ater Effect Enabled" +msgstr "~E~ffetto acqua attivo" + +#: sound/fmopl.cpp:51 +msgid "MAME OPL emulator" +msgstr "Emulatore OPL MAME" + +#: sound/fmopl.cpp:53 +msgid "DOSBox OPL emulator" +msgstr "Emulatore OPL DOSBox" + +#: sound/null.h:45 +msgid "No music" +msgstr "Nessuna musica" + +#: sound/softsynth/adlib.cpp:1590 +msgid "AdLib Emulator" +msgstr "Emulatore AdLib" + +#: sound/softsynth/mt32.cpp:327 +msgid "Initialising MT-32 Emulator" +msgstr "Avvio in corso dell'emulatore MT-32" + +#: sound/softsynth/mt32.cpp:541 +msgid "MT-32 Emulator" +msgstr "Emulatore MT-32" + +#: sound/softsynth/pcspk.cpp:142 +msgid "PC Speaker Emulator" +msgstr "Emulatore PC Speaker" + +#: sound/softsynth/pcspk.cpp:161 +msgid "IBM PCjr Emulator" +msgstr "Emulatore IBM PCjr" + +#: sound/softsynth/ym2612.cpp:762 +msgid "FM Towns Emulator" +msgstr "Emulatore FM Towns" + +#: backends/keymapper/remap-dialog.cpp:49 +msgid "Keymap:" +msgstr "Mappa tasti:" + +#: backends/keymapper/remap-dialog.cpp:66 +msgid " (Active)" +msgstr " (Attivo)" + +#: backends/keymapper/remap-dialog.cpp:100 +msgid " (Global)" +msgstr " (Globale)" + +#: backends/keymapper/remap-dialog.cpp:110 +msgid " (Game)" +msgstr " (Gioco)" + +#: backends/midi/windows.cpp:157 +msgid "Windows MIDI" +msgstr "MIDI Windows" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:60 +msgid "ScummVM Main Menu" +msgstr "Menu principale di ScummVM" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:66 +msgid "~L~eft handed mode" +msgstr "~M~odalità mancini" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:67 +msgid "~I~ndy fight controls" +msgstr "Controlli combattimento di ~I~ndy" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:68 +msgid "Show mouse cursor" +msgstr "Mostra cursore del mouse" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:69 +msgid "Snap to edges" +msgstr "Aggancia ai bordi" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:71 +msgid "Touch X Offset" +msgstr "Compensa X del tocco" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:78 +msgid "Touch Y Offset" +msgstr "Compensa Y del tocco" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:90 +msgid "Use laptop trackpad-style cursor control" +msgstr "Utilizza il controllo del cursore stile trackpad del portatile" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:91 +msgid "Tap for left click, double tap right click" +msgstr "Un tocco per il clic sinistro, doppio tocco per il clic destro" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:93 +msgid "Sensitivity" +msgstr "Sensibilità" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:102 +msgid "Initial top screen scale:" +msgstr "Schermo in primo piano:" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:108 +msgid "Main screen scaling:" +msgstr "Schermo principale:" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:110 +msgid "Hardware scale (fast, but low quality)" +msgstr "Ridimensionamento hardware (veloce, ma di bassa qualità)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:111 +msgid "Software scale (good quality, but slower)" +msgstr "Ridimensionamento software (di buona qualità, ma più lento)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:112 +msgid "Unscaled (you must scroll left and right)" +msgstr "Non ridimensionato (devi scorrere a sinistra e a destra)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:114 +msgid "Brightness:" +msgstr "Luminosità:" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:124 +msgid "High quality audio (slower) (reboot)" +msgstr "Audio ad alta qualità (più lento) (riavviare)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:125 +msgid "Disable power off" +msgstr "Disattiva spegnimento in chiusura" + +#: backends/platform/iphone/osys_events.cpp:339 +msgid "Touchpad mode enabled." +msgstr "Modalità touchpad attivata." + +#: backends/platform/iphone/osys_events.cpp:341 +msgid "Touchpad mode disabled." +msgstr "Modalità touchpad disattivata." + +#: backends/platform/sdl/graphics.cpp:40 +#: backends/platform/wince/wince-sdl.cpp:111 +#: backends/platform/wince/wince-sdl.cpp:118 +msgid "Normal (no scaling)" +msgstr "Normale (nessun ridimensionamento)" + +#: backends/platform/symbian/src/SymbianActions.cpp:41 +#: backends/platform/wince/CEActionsSmartphone.cpp:38 +msgid "Up" +msgstr "Su" + +#: backends/platform/symbian/src/SymbianActions.cpp:42 +#: backends/platform/wince/CEActionsSmartphone.cpp:39 +msgid "Down" +msgstr "Giù" + +#: backends/platform/symbian/src/SymbianActions.cpp:43 +#: backends/platform/wince/CEActionsSmartphone.cpp:40 +msgid "Left" +msgstr "Sinistra" + +#: backends/platform/symbian/src/SymbianActions.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:41 +msgid "Right" +msgstr "Destra" + +#: backends/platform/symbian/src/SymbianActions.cpp:45 +#: backends/platform/wince/CEActionsPocket.cpp:59 +#: backends/platform/wince/CEActionsSmartphone.cpp:42 +msgid "Left Click" +msgstr "Clic sinistro" + +#: backends/platform/symbian/src/SymbianActions.cpp:46 +#: backends/platform/wince/CEActionsSmartphone.cpp:43 +msgid "Right Click" +msgstr "Clic destro" + +#: backends/platform/symbian/src/SymbianActions.cpp:49 +#: backends/platform/wince/CEActionsSmartphone.cpp:46 +msgid "Zone" +msgstr "Zona" + +#: backends/platform/symbian/src/SymbianActions.cpp:50 +#: backends/platform/wince/CEActionsPocket.cpp:53 +#: backends/platform/wince/CEActionsSmartphone.cpp:47 +msgid "Multi Function" +msgstr "Multifunzione" + +#: backends/platform/symbian/src/SymbianActions.cpp:51 +msgid "Swap character" +msgstr "Cambia personaggio" + +#: backends/platform/symbian/src/SymbianActions.cpp:52 +msgid "Skip text" +msgstr "Salta testo" + +#: backends/platform/symbian/src/SymbianActions.cpp:54 +msgid "Fast mode" +msgstr "Modalità veloce" + +#: backends/platform/symbian/src/SymbianActions.cpp:55 +#: backends/platform/wince/CEActionsPocket.cpp:43 +#: backends/platform/wince/CEActionsSmartphone.cpp:51 +msgid "Quit" +msgstr "Esci" + +#: backends/platform/symbian/src/SymbianActions.cpp:56 +msgid "Debugger" +msgstr "Debugger" + +#: backends/platform/symbian/src/SymbianActions.cpp:57 +msgid "Global menu" +msgstr "Menu globale" + +#: backends/platform/symbian/src/SymbianActions.cpp:58 +msgid "Virtual keyboard" +msgstr "Tastiera virtuale" + +#: backends/platform/symbian/src/SymbianActions.cpp:59 +msgid "Key mapper" +msgstr "Programmatore tasti" + +#: backends/platform/symbian/src/SymbianOS.cpp:446 +msgid "Do you want to quit ?" +msgstr "Sei sicuro di voler uscire?" + +#: backends/platform/wii/options.cpp:51 +msgid "Video" +msgstr "Video" + +#: backends/platform/wii/options.cpp:54 +msgid "Current video mode:" +msgstr "Modalità video attuale:" + +#: backends/platform/wii/options.cpp:56 +msgid "Double-strike" +msgstr "Double-strike" + +#: backends/platform/wii/options.cpp:60 +msgid "Horizontal underscan:" +msgstr "Underscan orizzontale:" + +#: backends/platform/wii/options.cpp:66 +msgid "Vertical underscan:" +msgstr "Underscan verticale:" + +#: backends/platform/wii/options.cpp:71 +msgid "Input" +msgstr "Input" + +#: backends/platform/wii/options.cpp:74 +msgid "GC Pad sensitivity:" +msgstr "Sensibilità pad GC:" + +#: backends/platform/wii/options.cpp:80 +msgid "GC Pad acceleration:" +msgstr "Accelerazione pad GC:" + +#: backends/platform/wii/options.cpp:86 +msgid "DVD" +msgstr "DVD" + +#: backends/platform/wii/options.cpp:89 backends/platform/wii/options.cpp:101 +msgid "Status:" +msgstr "Stato:" + +#: backends/platform/wii/options.cpp:90 backends/platform/wii/options.cpp:102 +msgid "Unknown" +msgstr "Sconosciuto" + +#: backends/platform/wii/options.cpp:93 +msgid "Mount DVD" +msgstr "Monta DVD" + +#: backends/platform/wii/options.cpp:94 +msgid "Unmount DVD" +msgstr "Smonta DVD" + +#: backends/platform/wii/options.cpp:98 +msgid "SMB" +msgstr "SMB" + +#: backends/platform/wii/options.cpp:106 +msgid "Server:" +msgstr "Server:" + +#: backends/platform/wii/options.cpp:110 +msgid "Share:" +msgstr "Condivisione:" + +#: backends/platform/wii/options.cpp:114 +msgid "Username:" +msgstr "Nome utente:" + +#: backends/platform/wii/options.cpp:118 +msgid "Password:" +msgstr "Password:" + +#: backends/platform/wii/options.cpp:121 +msgid "Init network" +msgstr "Avvia rete" + +#: backends/platform/wii/options.cpp:123 +msgid "Mount SMB" +msgstr "Monta SMB" + +#: backends/platform/wii/options.cpp:124 +msgid "Unmount SMB" +msgstr "Smonta SMB" + +#: backends/platform/wii/options.cpp:145 +msgid "DVD Mounted successfully" +msgstr "DVD montato con successo" + +#: backends/platform/wii/options.cpp:148 +msgid "Error while mounting the DVD" +msgstr "Errore nel montare il DVD" + +#: backends/platform/wii/options.cpp:150 +msgid "DVD not mounted" +msgstr "DVD non montato" + +#: backends/platform/wii/options.cpp:163 +msgid "Network up, share mounted" +msgstr "Rete attiva, condivisione montata" + +#: backends/platform/wii/options.cpp:165 +msgid "Network up" +msgstr "Rete attiva" + +#: backends/platform/wii/options.cpp:168 +msgid ", error while mounting the share" +msgstr ", errore nel montare la condivisione" + +#: backends/platform/wii/options.cpp:170 +msgid ", share not mounted" +msgstr ", condivisione non montata" + +#: backends/platform/wii/options.cpp:176 +msgid "Network down" +msgstr "Rete disattivata" + +#: backends/platform/wii/options.cpp:180 +msgid "Initialising network" +msgstr "Avvio rete in corso" + +#: backends/platform/wii/options.cpp:184 +msgid "Timeout while initialising network" +msgstr "Attesa per l'avvio della rete" + +#: backends/platform/wii/options.cpp:188 +#, c-format +msgid "Network not initialsed (%d)" +msgstr "Rete non avviata (%d)" + +#: backends/platform/wince/CEActionsPocket.cpp:45 +msgid "Hide Toolbar" +msgstr "Nascondi la barra degli strumenti" + +#: backends/platform/wince/CEActionsPocket.cpp:46 +msgid "Show Keyboard" +msgstr "Mostra tastiera" + +#: backends/platform/wince/CEActionsPocket.cpp:47 +msgid "Sound on/off" +msgstr "Suono on/off" + +#: backends/platform/wince/CEActionsPocket.cpp:48 +msgid "Right click" +msgstr "Clic destro" + +#: backends/platform/wince/CEActionsPocket.cpp:49 +msgid "Show/Hide Cursor" +msgstr "Mostra/nascondi cursore" + +#: backends/platform/wince/CEActionsPocket.cpp:50 +msgid "Free look" +msgstr "Osservazione libera" + +#: backends/platform/wince/CEActionsPocket.cpp:51 +msgid "Zoom up" +msgstr "Zoom avanti" + +#: backends/platform/wince/CEActionsPocket.cpp:52 +msgid "Zoom down" +msgstr "Zoom indietro" + +#: backends/platform/wince/CEActionsPocket.cpp:54 +#: backends/platform/wince/CEActionsSmartphone.cpp:48 +msgid "Bind Keys" +msgstr "Associa tasti" + +#: backends/platform/wince/CEActionsPocket.cpp:55 +msgid "Cursor Up" +msgstr "Cursore su" + +#: backends/platform/wince/CEActionsPocket.cpp:56 +msgid "Cursor Down" +msgstr "Cursore giù" + +#: backends/platform/wince/CEActionsPocket.cpp:57 +msgid "Cursor Left" +msgstr "Cursore a sinistra" + +#: backends/platform/wince/CEActionsPocket.cpp:58 +msgid "Cursor Right" +msgstr "Cursore a destra" + +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Do you want to load or save the game?" +msgstr "Vuoi caricare o salvare il gioco?" + +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +msgid " Are you sure you want to quit ? " +msgstr " Sei sicuro di voler uscire? " + +#: backends/platform/wince/CEActionsSmartphone.cpp:49 +msgid "Keyboard" +msgstr "Tastiera" + +#: backends/platform/wince/CEActionsSmartphone.cpp:50 +msgid "Rotate" +msgstr "Rotazione" + +#: backends/platform/wince/CELauncherDialog.cpp:58 +msgid "Using SDL driver " +msgstr "Utilizzo del driver SDL " + +#: backends/platform/wince/CELauncherDialog.cpp:62 +msgid "Display " +msgstr "Visualizza " + +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "Do you want to perform an automatic scan ?" +msgstr "Vuoi eseguire una scansione automatica?" diff --git a/po/module.mk b/po/module.mk new file mode 100644 index 0000000000..eb9a85e4e3 --- /dev/null +++ b/po/module.mk @@ -0,0 +1,43 @@ +POTFILE := $(srcdir)/po/scummvm.pot +POFILES := $(wildcard $(srcdir)/po/*.po) + +updatepot: + xgettext -f $(srcdir)/po/POTFILES -D $(srcdir) -d scummvm --c++ -k_ -k_s -o $(POTFILE) \ + "--copyright-holder=ScummVM Team" --package-name=ScummVM \ + --package-version=$(VERSION) --msgid-bugs-address=scummvm-devel@lists.sf.net -o $(POTFILE)_ + + sed -e 's/SOME DESCRIPTIVE TITLE/LANGUAGE translation for ScummVM/' \ + -e 's/UTF-8/CHARSET/' -e 's/PACKAGE/ScummVM/' $(POTFILE)_ > $(POTFILE).new + + rm $(POTFILE)_ + if test -f $(POTFILE); then \ + sed -f $(srcdir)/po/remove-potcdate.sed < $(POTFILE) > $(POTFILE).1 && \ + sed -f $(srcdir)/po/remove-potcdate.sed < $(POTFILE).new > $(POTFILE).2 && \ + if cmp $(POTFILE).1 $(POTFILE).2 >/dev/null 2>&1; then \ + rm -f $(POTFILE).new; \ + else \ + rm -f $(POTFILE) && \ + mv -f $(POTFILE).new $(POTFILE); \ + fi; \ + rm -f $(POTFILE).1 $(POTFILE).2; \ + else \ + mv -f $(POTFILE).new $(POTFILE); \ + fi; + +%.po: $(POTFILE) + msgmerge $@ $(POTFILE) -o $@.new + if cmp $@ $@.new >/dev/null 2>&1; then \ + rm -f $@.new; \ + else \ + mv -f $@.new $@; \ + fi; + +#$(srcdir)/common/messages.cpp: $(POFILES) +# perl $(srcdir)/tools/po2c $^ > $(srcdir)/common/messages.cpp + +update-translations: updatepot $(POFILES) + @$(foreach file, $(POFILES), echo -n $(notdir $(basename $(file)))": ";msgfmt --statistic $(file);) + @rm -f messages.mo + perl $(srcdir)/tools/po2c $(POFILES) > $(srcdir)/common/messages.cpp + +.PHONY: updatepot update-translations diff --git a/po/remove-potcdate.sed b/po/remove-potcdate.sed new file mode 100644 index 0000000000..2436c49e78 --- /dev/null +++ b/po/remove-potcdate.sed @@ -0,0 +1,19 @@ +# Sed script that remove the POT-Creation-Date line in the header entry +# from a POT file. +# +# The distinction between the first and the following occurrences of the +# pattern is achieved by looking at the hold space. +/^"POT-Creation-Date: .*"$/{ +x +# Test if the hold space is empty. +s/P/P/ +ta +# Yes it was empty. First occurrence. Remove the line. +g +d +bb +:a +# The hold space was nonempty. Following occurrences. Do nothing. +x +:b +} diff --git a/po/ru_RU.po b/po/ru_RU.po new file mode 100644 index 0000000000..2d4a96b63c --- /dev/null +++ b/po/ru_RU.po @@ -0,0 +1,1361 @@ +# Russian translation for ScummVM. +# Copyright (C) 2010 ScummVM +# This file is distributed under the same license as the ScummVM package. +# Eugene Sandulenko <sev@scummvm.org>, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: ScummVM VERSION\n" +"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n" +"POT-Creation-Date: 2010-07-12 17:44+0200\n" +"PO-Revision-Date: 2010-06-13 20:55+0300\n" +"Last-Translator: Eugene Sandulenko <sev@scummvm.org>\n" +"Language-Team: Russian\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=iso-8859-5\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n" +"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +#: gui/about.cpp:96 +#, c-format +msgid "(built on %s)" +msgstr "(áÞÑàÐÝ %s)" + +#: gui/about.cpp:103 +msgid "Features compiled in:" +msgstr "²ÚÛîçÕÝÝëÕ Ò ÑØÛÔ ÞßæØØ:" + +#: gui/about.cpp:112 +msgid "Available engines:" +msgstr "´ÞáâãßÝëÕ ÔÒØÖÚØ:" + +#: gui/browser.cpp:69 +msgid "Go up" +msgstr "²ÒÕàå" + +#: gui/browser.cpp:69 +msgid "Go to previous directory level" +msgstr "¿ÕàÕÙâØ ÝÐ ÔØàÕÚâÞàØî ãàÞÒÝÕÜ ÒëèÕ" + +#: gui/browser.cpp:70 gui/chooser.cpp:49 gui/KeysDialog.cpp:46 +#: gui/launcher.cpp:266 gui/massadd.cpp:95 gui/options.cpp:972 +#: gui/saveload.cpp:65 gui/saveload.cpp:157 gui/themebrowser.cpp:56 +#: backends/platform/wii/options.cpp:48 +msgid "Cancel" +msgstr "¾âÜÕÝÐ" + +#: gui/browser.cpp:71 gui/chooser.cpp:50 gui/themebrowser.cpp:57 +msgid "Choose" +msgstr "²ëÑàÐâì" + +#: gui/GuiManager.cpp:102 backends/keymapper/remap-dialog.cpp:54 +msgid "Close" +msgstr "·ÐÚàëâì" + +#: gui/GuiManager.cpp:105 +msgid "Mouse click" +msgstr "ºÛØÚ Üëèìî" + +#: gui/GuiManager.cpp:108 base/main.cpp:285 +msgid "Display keyboard" +msgstr "¿ÞÚÐ×Ðâì ÚÛÐÒØÐâãàã" + +#: gui/GuiManager.cpp:111 base/main.cpp:288 +msgid "Remap keys" +msgstr "¿ÕàÕÝÐ×ÝÐçØâì ÚÛÐÒØèØ" + +#: gui/KeysDialog.cpp:44 +msgid "Map" +msgstr "½Ð×ÝÐçØâì" + +#: gui/KeysDialog.cpp:45 gui/launcher.cpp:267 gui/launcher.cpp:873 +#: gui/launcher.cpp:877 gui/massadd.cpp:92 gui/options.cpp:973 +#: backends/platform/wii/options.cpp:47 +#: backends/platform/wince/CELauncherDialog.cpp:56 +msgid "OK" +msgstr "OK" + +#: gui/KeysDialog.cpp:52 +msgid "Select an action and click 'Map'" +msgstr "²ëÑÕàØâÕ ÔÕÙáâÒØÕ Ø ÚÛØÚÝØâÕ '½Ð×ÝÐçØâì'" + +#: gui/KeysDialog.cpp:83 gui/KeysDialog.cpp:105 gui/KeysDialog.cpp:144 +#, c-format +msgid "Associated key : %s" +msgstr "½Ð×ÝÐçÕÝÝÐï ÚÛÐÒØèÐ : %s" + +#: gui/KeysDialog.cpp:85 gui/KeysDialog.cpp:107 gui/KeysDialog.cpp:146 +#, c-format +msgid "Associated key : none" +msgstr "½Ð×ÝÐçÕÝÝÐï ÚÛÐÒØèÐ : ÝÕâ" + +#: gui/KeysDialog.cpp:93 +msgid "Please select an action" +msgstr "¿ÞÖÐÛãÙáâÐ, ÒëÑÕàØâÕ ÔÕÙáâÒØÕ" + +#: gui/KeysDialog.cpp:109 +msgid "Press the key to associate" +msgstr "½ÐÖÜØâÕ ÚÛÐÒØèã ÔÛï ÝÐ×ÝÐçÕÝØï" + +#: gui/KeysDialog.cpp:148 +msgid "Choose an action to map" +msgstr "²ëÑÕàØâÕ ÔÕÙáâÒØÕ ÔÛï ÝÐ×ÝÐçÕÝØï" + +#: gui/launcher.cpp:170 +msgid "Game" +msgstr "¸ÓàÐ" + +#: gui/launcher.cpp:173 +msgid "ID:" +msgstr "ID:" + +#: gui/launcher.cpp:173 gui/launcher.cpp:174 +msgid "" +"Short game identifier used for referring to savegames and running the game " +"from the command line" +msgstr "" +"ºÞàÞâÚØÙ ØÔÕÝâØäØÚÐâÞà, ØáßÞÛì×ãÕÜëÙ ÔÛï ØÜÕÝ áÞåàÐÝÕÝØÙ ØÓà Ø ÔÛï ×ÐßãáÚÐ " +"Ø× ÚÞÜÐÝÔÝÞÙ áâàÞÚØ" + +#: gui/launcher.cpp:177 +msgid "Name:" +msgstr "½Ð×ÒÐÝØÕ:" + +#: gui/launcher.cpp:177 gui/launcher.cpp:178 +msgid "Full title of the game" +msgstr "¿ÞÛÝÞÕ ÝÐ×ÒÐÝØÕ ØÓàë" + +#: gui/launcher.cpp:181 +msgid "Language:" +msgstr "Ï×ëÚ:" + +#: gui/launcher.cpp:181 gui/launcher.cpp:182 +msgid "" +"Language of the game. This will not turn your Spanish game version into " +"English" +msgstr "" +"Ï×ëÚ ØÓàë. ¸×ÜÕÝÕÝØÕ íâÞÓÞ ßÐàÐÜÕâàÐ ÝÕ ßàÕÒàÐâØâ ØÓàã ÝÐ ÐÝÓÛØÙáÚÞÜ Ò " +"àãááÚãî" + +#: gui/launcher.cpp:183 gui/launcher.cpp:194 gui/options.cpp:80 +#: gui/options.cpp:617 gui/options.cpp:627 gui/options.cpp:943 +#: sound/null.cpp:42 +msgid "<default>" +msgstr "<ßÞ ãÜÞÛçÐÝØî>" + +#: gui/launcher.cpp:192 +msgid "Platform:" +msgstr "¿ÛÐâäÞàÜÐ:" + +#: gui/launcher.cpp:192 gui/launcher.cpp:193 +msgid "Platform the game was originally designed for" +msgstr "¿ÛÐâäÞàÜÐ, ÔÛï ÚÞâÞàÞÙ ØÓàÐ ÑëÛÐ Ø×ÝÐçÐÛìÝÞ àÐ×àÐÑÞâÐÝÐ" + +#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867 +msgid "Graphics" +msgstr "³àÐäØÚÐ" + +#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867 +msgid "GFX" +msgstr "³àä" + +#: gui/launcher.cpp:206 +msgid "Override global graphic settings" +msgstr "¿ÕàÕÚàëâì ÓÛÞÑÐÛìÝëÕ ãáâÐÝÞÒÚØ ÓàÐäØÚØ" + +#: gui/launcher.cpp:213 gui/options.cpp:873 +msgid "Audio" +msgstr "°ãÔØÞ" + +#: gui/launcher.cpp:215 +msgid "Override global audio settings" +msgstr "¿ÕàÕÚàëâì ÓÛÞÑÐÛìÝëÕ ãáâÐÝÞÒÚØ ÐãÔØÞ" + +#: gui/launcher.cpp:223 gui/options.cpp:877 +msgid "Volume" +msgstr "³àÞÜÚÞáâì" + +#: gui/launcher.cpp:225 +msgid "Override global volume settings" +msgstr "¿ÕàÕÚàëâì ÓÛÞÑÐÛìÝëÕ ãáâÐÝÞÒÚØ ÓàÞÜÚÞáâØ" + +#: gui/launcher.cpp:232 gui/options.cpp:885 +msgid "MIDI" +msgstr "MIDI" + +#: gui/launcher.cpp:234 +msgid "Override global MIDI settings" +msgstr "¿ÕàÕÚàëâì ÓÛÞÑÐÛìÝëÕ ãáâÐÝÞÒÚØ MIDI" + +#: gui/launcher.cpp:244 gui/options.cpp:891 +msgid "Paths" +msgstr "¿ãâØ" + +#: gui/launcher.cpp:250 +msgid "Game Path:" +msgstr "¿ãâì Ú ØÓàÕ: " + +#: gui/launcher.cpp:254 gui/options.cpp:904 +msgid "Extra Path:" +msgstr "´Þß. ßãâì:" + +#: gui/launcher.cpp:254 gui/launcher.cpp:255 +msgid "Specifies path to additional data used the game" +msgstr "ÃÚÐ×ëÒÐÕâ ßãâì Ú ÔÞßÞÛÝØâÕÛìÝëÜ äÐÙÛÐÜ ÔÐÝÝëå ÔÛï ØÓàë" + +#: gui/launcher.cpp:258 +msgid "Save Path:" +msgstr "¿ãâì áÞåà.: " + +#: gui/launcher.cpp:258 gui/launcher.cpp:259 gui/options.cpp:898 +#: gui/options.cpp:899 +msgid "Specifies where your savegames are put" +msgstr "ÃÚÐ×ëÒÐÕâ ßãâì Ú áÞåàÐÝÕÝØïÜ ØÓàë" + +#: gui/launcher.cpp:275 gui/launcher.cpp:353 gui/launcher.cpp:398 +#: gui/options.cpp:245 gui/options.cpp:400 gui/options.cpp:486 +#: gui/options.cpp:545 gui/options.cpp:706 gui/options.cpp:902 +#: gui/options.cpp:905 gui/options.cpp:909 gui/options.cpp:996 +#: gui/options.cpp:1002 gui/options.cpp:1008 gui/options.cpp:1016 +#: gui/options.cpp:1040 gui/options.cpp:1044 gui/options.cpp:1050 +#: gui/options.cpp:1057 gui/options.cpp:1156 +msgid "None" +msgstr "½Õ ×ÐÔÐÝ" + +#: gui/launcher.cpp:280 gui/launcher.cpp:357 +#: backends/platform/wii/options.cpp:56 +msgid "Default" +msgstr "¿Þ ãÜÞÛçÐÝØî" + +#: gui/launcher.cpp:391 gui/options.cpp:1150 +msgid "Select SoundFont" +msgstr "²ëÑÕàØâÕ SoundFont" + +#: gui/launcher.cpp:410 gui/launcher.cpp:548 +msgid "Select directory with game data" +msgstr "²ëÑÕàØâÕ ÔØàÕÚâÞàØî á äÐÙÛÐÜØ ØÓàë" + +#: gui/launcher.cpp:428 +msgid "Select additional game directory" +msgstr "²ëÑÕàØâÕ ÔÞßÞÛÝØâÕÛìÝãî ÔØàÕÚâÞàØî ØÓàë" + +#: gui/launcher.cpp:440 +msgid "Select directory for saved games" +msgstr "²ëÑÕàØâÕ ÔØàÕÚâÞàØî ÔÛï áÞåàÐÝÕÝØÙ" + +#: gui/launcher.cpp:459 +msgid "This game ID is already taken. Please choose another one." +msgstr "ÍâÞâ ID ØÓàë ãÖÕ ØáßÞÛì×ãÕâáï. ¿ÞÖÐÛãÙáâÐ, ÒëÑÕàØâÕ ÔàãÓÞÙ." + +#: gui/launcher.cpp:500 engines/dialogs.cpp:113 +msgid "~Q~uit" +msgstr "~²~ëåÞÔ" + +#: gui/launcher.cpp:500 +msgid "Quit ScummVM" +msgstr "²ëåÞÔ Ø× ScummVM" + +#: gui/launcher.cpp:501 +msgid "A~b~out..." +msgstr "¾ ß~à~ÞÓàÐÜÜÕ..." + +#: gui/launcher.cpp:501 +msgid "About ScummVM" +msgstr "¾ ßàÞÓàÐÜÜÕ ScummVM" + +#: gui/launcher.cpp:502 +msgid "~O~ptions..." +msgstr "~¾~ßæØØ..." + +#: gui/launcher.cpp:502 +msgid "Change global ScummVM options" +msgstr "¸×ÜÕÝØâì ÓÛÞÑÐÛìÝëÕ ÞßæØØ ScummVM" + +#: gui/launcher.cpp:504 +msgid "~S~tart" +msgstr "¿~ã~áÚ" + +#: gui/launcher.cpp:504 +msgid "Start selected game" +msgstr "·ÐßãáâØâì ÒëÑàÐÝÝãî ØÓàã" + +#: gui/launcher.cpp:507 +msgid "~L~oad..." +msgstr "~·~ÐÓà...." + +#: gui/launcher.cpp:507 +msgid "Load savegame for selected game" +msgstr "·ÐÓàãרâì áÞåàÝÕÝØÕ ÔÛï ÒëÑàÐÝÝÞÙ ØÓàë" + +#: gui/launcher.cpp:511 +msgid "~A~dd Game..." +msgstr "~´~ÞÑ. ØÓàã..." + +#: gui/launcher.cpp:511 +msgid "Hold Shift for Mass Add" +msgstr "ÃÔÕàÖØÒÐÙâÕ ÚÛÐÒØèã Shift ÔÛï âÞÓÞ, çâÞÑë ÔÞÑÐÒØâì ÝÕáÚÞÛìÚÞ ØÓà" + +#: gui/launcher.cpp:513 +msgid "~E~dit Game..." +msgstr "¸×~Ü~. ØÓàã..." + +#: gui/launcher.cpp:513 +msgid "Change game options" +msgstr "¸×ÜÕÝØâì ÞßæØØ ØÓàë" + +#: gui/launcher.cpp:515 +msgid "~R~emove Game" +msgstr "~Ã~ÔÐÛØâì ØÓàã" + +#: gui/launcher.cpp:515 +msgid "Remove game from the list. The game data files stay intact" +msgstr "ÃÔÐÛØâì ØÓàã Ø× áߨáÚÐ. ½Õ ãÔÐÛïÕâ ØÓàã á ÖÕáâÚÞÓÞ ÔØáÚÐ" + +#: gui/launcher.cpp:522 +msgid "Search in game list" +msgstr "¿ÞØáÚ Ò áߨáÚÕ ØÓà" + +#: gui/launcher.cpp:526 gui/launcher.cpp:1037 +msgid "Search:" +msgstr "¿ÞØáÚ:" + +#: gui/launcher.cpp:529 gui/options.cpp:707 +msgid "Clear value" +msgstr "¾çØáâØâì ×ÝÐçÕÝØÕ" + +#: gui/launcher.cpp:551 engines/dialogs.cpp:117 +msgid "Load game:" +msgstr "·ÐÓàãרâì ØÓàã:" + +#: gui/launcher.cpp:551 engines/dialogs.cpp:117 +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Load" +msgstr "·ÐÓàãרâì" + +#: gui/launcher.cpp:660 +msgid "" +"Do you really want to run the mass game detector? This could potentially add " +"a huge number of games." +msgstr "" +"²ë ÔÕÙáâÒØâÕÛìÝÞ åÞâØâÕ ×ÐßãáâØâì ÔÕâÕÚâÞà ÒáÕå ØÓà? ÍâÞ ßÞâÕÝæØÐÛìÝÞ ÜÞÖÕâ " +"ÔÞÑÐÒØâì ÑÞÛìèÞÕ ÚÞÛØçÕáâÒÞ ØÓà." + +#: gui/launcher.cpp:661 gui/launcher.cpp:810 +#: backends/platform/symbian/src/SymbianOS.cpp:446 +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "Yes" +msgstr "´Ð" + +#: gui/launcher.cpp:661 gui/launcher.cpp:810 +#: backends/platform/symbian/src/SymbianOS.cpp:446 +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "No" +msgstr "½Õâ" + +#: gui/launcher.cpp:708 +msgid "ScummVM couldn't open the specified directory!" +msgstr "ScummVM ÝÕ ÜÞÖÕâ ÞâÚàëâì ãÚÐ×ÐÝÝãî ÔØàÕÚâÞàØî!" + +#: gui/launcher.cpp:720 +msgid "ScummVM could not find any game in the specified directory!" +msgstr "ScummVM ÝÕ ÜÞÖÕâ ÝÐÙâØ ØÓàã Ò ãÚÐ×ÐÝÝÞÙ ÔØàÕÚâÞàØØ!" + +#: gui/launcher.cpp:734 +msgid "Pick the game:" +msgstr "²ëÑÕàØâÕ ØÓàã:" + +#: gui/launcher.cpp:810 +msgid "Do you really want to remove this game configuration?" +msgstr "²ë ÔÕÙáâÒØâÕÛìÝÞ åÞâØâÕ ãÔÐÛØâì ãáâÐÝÞÒÚØ ÔÛï íâÞÙ ØÓàë?" + +#: gui/launcher.cpp:873 +msgid "This game does not support loading games from the launcher." +msgstr "ÍâÐ ØÓàÐ ÝÕ ßÞÔÔÕàÖØÒÐÕâ ×ÐÓàã×Úã áÞåàÐÝÕÝØÙ çÕàÕ× ÓÛÐÒÝÞÕ ÜÕÝî." + +#: gui/launcher.cpp:877 +msgid "ScummVM could not find any engine capable of running the selected game!" +msgstr "ScummVM ÝÕ áÜÞÓ ÝÐÙâØ ÔÒØÖÞÚ ÔÛï ×ÐßãáÚÐ ÒëÑàÐÝÝÞÙ ØÓàë!" + +#: gui/launcher.cpp:989 +msgid "Mass Add..." +msgstr "´ÞÑ. ÜÝÞÓÞ..." + +#: gui/launcher.cpp:990 +msgid "Add Game..." +msgstr "½ÞÒ. ØÓàÐ..." + +#: gui/massadd.cpp:79 gui/massadd.cpp:82 +msgid "... progress ..." +msgstr "... Øéã ..." + +#: gui/massadd.cpp:244 +msgid "Scan complete!" +msgstr "¿ÞØáÚ ×ÐÚÞÝçÕÝ!" + +#: gui/massadd.cpp:247 +#, c-format +msgid "Discovered %d new games." +msgstr "½ÐÙÔÕÝÞ %d ÝÞÒëå ØÓà." + +#: gui/massadd.cpp:251 +#, c-format +msgid "Scanned %d directories ..." +msgstr "¿àÞáÜÞâàÕÝÞ %d ÔØàÕÚâÞàØÙ ..." + +#: gui/massadd.cpp:254 +#, c-format +msgid "Discovered %d new games ..." +msgstr "½ÐÙÔÕÝÞ %d ÝÞÒëå ØÓà ..." + +#: gui/options.cpp:78 +msgid "Never" +msgstr "½ØÚÞÓÔÐ" + +#: gui/options.cpp:78 +msgid "every 5 mins" +msgstr "ÚÐÖÔëÕ 5 ÜØÝãâ" + +#: gui/options.cpp:78 +msgid "every 10 mins" +msgstr "ÚÐÖÔëÕ 10 ÜØÝãâ" + +#: gui/options.cpp:78 +msgid "every 15 mins" +msgstr "ÚÐÖÔëÕ 15 ÜØÝãâ" + +#: gui/options.cpp:78 +msgid "every 30 mins" +msgstr "ÚÐÖÔëÕ 30 ÜØÝãâ" + +#: gui/options.cpp:80 +msgid "8 kHz" +msgstr "8 Ú³æ" + +#: gui/options.cpp:80 +msgid "11kHz" +msgstr "11 Ú³æ" + +#: gui/options.cpp:80 +msgid "22 kHz" +msgstr "22 Ú³æ" + +#: gui/options.cpp:80 +msgid "44 kHz" +msgstr "44 Ú³æ" + +#: gui/options.cpp:80 +msgid "48 kHz" +msgstr "48 Ú³æ" + +#: gui/options.cpp:614 +msgid "Graphics mode:" +msgstr "³àÐäØçÕáÚØÙ àÕÖØÜ:" + +#: gui/options.cpp:625 +msgid "Render mode:" +msgstr "ÀÕÖØÜ àÐáâàØàÞÒÐÝØï:" + +#: gui/options.cpp:625 gui/options.cpp:626 +msgid "Special dithering modes supported by some games" +msgstr "ÁßÕæØÐÛìÝëÕ àÕÖØÜë àÕÝÔÕàØÝÓÐ, ßÞÔÔÕàÖØÒÐÕÜëÕ ÝÕÚÞâÞàëÜØ ØÓàÐÜØ" + +#: gui/options.cpp:635 +msgid "Fullscreen mode" +msgstr "¿ÞÛÝÞíÚàÐÝÝëÙ àÕÖØÜ" + +#: gui/options.cpp:638 +msgid "Aspect ratio correction" +msgstr "ºÞààÕÚæØï áÞÞâÝÞèÕÝØï áâÞàÞÝ" + +#: gui/options.cpp:638 +msgid "Correct aspect ratio for 320x200 games" +msgstr "ºÞààÕÚâØàÞÒÐâì áÞÞâÝÞèÕÝØÕ áâÞàÞÝ ÔÛï ØÓà á àÐ×àÕèÕÝØÕÜ 320x200" + +#: gui/options.cpp:645 +msgid "Preferred Device:" +msgstr "¿àÕÔßÞçØâÐÕÜÞÕ ãáâàÞÙáâÒÞ:" + +#: gui/options.cpp:645 +#, fuzzy +msgid "Music Device:" +msgstr "ÃáâàÞÙâáÒÞ GM:" + +#: gui/options.cpp:645 +msgid "Specifies preferred sound device or sound card emulator" +msgstr "ÃÚÐ×ëÒÐÕâ ÒëåÞÔÝÞÕ ×ÒãÚÞÒÞÕ ãáâàÞÙáâÒÞ ØÛØ íÜãÛïâÞà ×ÒãÚÞÒÞÙ ÚÐàâë" + +#: gui/options.cpp:645 gui/options.cpp:646 +msgid "Specifies output sound device or sound card emulator" +msgstr "ÃÚÐ×ëÒÐÕâ ÒëåÞÔÝÞÕ ×ÒãÚÞÒÞÕ ãáâàÞÙáâÒÞ ØÛØ íÜãÛïâÞà ×ÒãÚÞÒÞÙ ÚÐàâë" + +#: gui/options.cpp:648 +#, fuzzy +msgid "MT-32 Device:" +msgstr "ÃáâàÞÙáâÒÞ MT32:" + +#: gui/options.cpp:648 +msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output" +msgstr "" +"ÃÚÐ×ëÒÐÕâ ×ÒãÚÞÒÞÕ ãáâàÞÙáâÒÞ ßÞ ãÜÞÛçÐÝØï ÔÛï ÒëÒÞÔÐ ÝÐ Roland MT-32/LAPC1/" +"CM32l/CM64" + +#: gui/options.cpp:650 +msgid "GM Device:" +msgstr "ÃáâàÞÙâáÒÞ GM:" + +#: gui/options.cpp:650 +msgid "Specifies default sound device for General MIDI output" +msgstr "ÃÚÐ×ëÒÐÕâ ÒëåÞÔÝÞÕ ×ÒãÚÞÒÞÕ ãáâàÞÙáâÒÞ ÔÛï MIDI" + +#: gui/options.cpp:682 +msgid "AdLib emulator:" +msgstr "ÍÜãÛïâÞà AdLib:" + +#: gui/options.cpp:682 gui/options.cpp:683 +msgid "AdLib is used for music in many games" +msgstr "·ÒãÚÞÒÐï ÚÐàâÐ AdLib ØáßÞÛì×ãÕâáï ÜÝÞÓØÜØ ØÓàÐÜØ" + +#: gui/options.cpp:693 +msgid "Output rate:" +msgstr "²ëåÞÔÝÐï çÐáâÞâÐ:" + +#: gui/options.cpp:693 gui/options.cpp:694 +msgid "" +"Higher value specifies better sound quality but may be not supported by your " +"soundcard" +msgstr "" +"±¾ÛìèØÕ ×ÝÐçÕÝØï ×ÐÔÐîâ ÛãçèÕÕ ÚÐçÕáâÒÞ ×ÒãÚÐ, ÞÔÝÐÚÞ ÞÝØ ÜÞÓãâ ÝÕ " +"ßÞÔÔÕàÖØÒÐâìáï ÒÐèÕÙ ×ÒãÚÞÒÞÙ ÚÐàâÞÙ" + +#: gui/options.cpp:705 +msgid "SoundFont:" +msgstr "SoundFont:" + +#: gui/options.cpp:705 gui/options.cpp:706 +msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity" +msgstr "" +"SoundFontë ßÞÔÔÕàÔÖØÒÐîâáï ÝÕÚÞâÞàëÜØ ×ÒãÚÞÒëÜØ ÚÐàâÐÜØ, Fluidsynth Ø " +"Timidity" + +#: gui/options.cpp:710 +msgid "Mixed AdLib/MIDI mode" +msgstr "ÁÜÕèÐÝÝëÙ àÕÖØÜ AdLib/MIDI" + +#: gui/options.cpp:710 +msgid "Use both MIDI and AdLib sound generation" +msgstr "¸áßÞÛì×ÞÒÐâì Ø MIDI Ø AdLib ÔÛï ÓÕÝÕàÐæØØ ×ÒãÚÐ" + +#: gui/options.cpp:713 +msgid "True Roland MT-32 (disable GM emulation)" +msgstr "½ÐáâÞïéØÙ Roland MT-32 (×ÐßàÕâØâì íÜãÛïæØî GM)" + +#: gui/options.cpp:713 +msgid "" +"Check if you want to use your real hardware Roland-compatible sound device " +"connected to your computer" +msgstr "" +"¾âÜÕâìâÕ, ÕáÛØ ã ÒÐá ßÞÔÚÛîçÕÝÞ Roland-áÞÒÜÕáâØÜÞÕ ×ÒãÚÞÒÞÕ ãáâàÞÙáâÒÞ Ø Òë " +"åÞâØâÕ ÕÓÞ ØáßÞÛì×ÞÒÐâì" + +#: gui/options.cpp:716 +msgid "Enable Roland GS Mode" +msgstr "²ÚÛîçØâì àÕÖØÜ Roland GS" + +#: gui/options.cpp:716 +msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack" +msgstr "" +"²ëÚÛîçÐÕâ ÜÐßߨÝÓ General MIDI ÔÛï ØÓà á ×ÒãÚÞÒÞÙ ÔÞàÞÖÚÞÙ ÔÛï Roland MT-32" + +#: gui/options.cpp:719 +msgid "MIDI gain:" +msgstr "ÃáØÛÕÝØÕ MIDI:" + +#: gui/options.cpp:732 +msgid "Text and Speech:" +msgstr "ÂÕÚáâ Ø Þ×ÒãçÚÐ:" + +#: gui/options.cpp:737 gui/options.cpp:743 +msgid "Speech" +msgstr "¾×ÒãçÚÐ" + +#: gui/options.cpp:738 gui/options.cpp:744 +msgid "Subtitles" +msgstr "ÁãÑâØâàë" + +#: gui/options.cpp:739 gui/options.cpp:745 +msgid "Both" +msgstr "²áñ" + +#: gui/options.cpp:743 +msgid "Spch" +msgstr "¾×Ò" + +#: gui/options.cpp:744 +msgid "Subs" +msgstr "ÁãÑ" + +#: gui/options.cpp:745 +msgid "Show subtitles and play speech" +msgstr "¿ÞÚÐ×ëÒÐâì áãÑâØâàë Ø ÒÞáßàÞØ×ÒÞÔØâì àÕçì" + +#: gui/options.cpp:749 +msgid "Subtitle speed:" +msgstr "ÁÚÞàÞáâì áãÑâØâàÞÒ:" + +#: gui/options.cpp:761 +msgid "Music volume:" +msgstr "³àÞÜÚÞáâì Üã×ëÚØ:" + +#: gui/options.cpp:768 +msgid "Mute All" +msgstr "²ëÚÛîçØâì Òáñ" + +#: gui/options.cpp:771 +msgid "SFX volume:" +msgstr "³àÞÜÚÞáâì íääÕÚâÞÒ:" + +#: gui/options.cpp:771 gui/options.cpp:772 +msgid "Special sound effects volume" +msgstr "³àÞÜÚÞáâì áßÕæØÐÛìÝëå ×ÒãÚÞÒëå íääÕÚâÞÒ" + +#: gui/options.cpp:778 +msgid "Speech volume:" +msgstr "³àÞÜÚÞáâì Þ×ÒãçÚØ:" + +#: gui/options.cpp:898 +msgid "Save Path: " +msgstr "¿ãâì ÔÛï áÞåàÐÝÕÝØÙ: " + +#: gui/options.cpp:901 +msgid "Theme Path:" +msgstr "¿ãâì Ú âÕÜÐÜ:" + +#: gui/options.cpp:904 gui/options.cpp:905 +msgid "Specifies path to additional data used by all games or ScummVM" +msgstr "" +"ÃÚÐ×ëÒÐÕâ ßãâì Ú ÔÞßÞÛÝØâÕÛìÝëÜ äÐÙÛÐÜ ÔÐÝÝëå, ØáßÞÛì×ãÕÜëå ÒáÕÜØ ØÓàÐÜØ, " +"ÛØÑÞ ScummVM" + +#: gui/options.cpp:908 +msgid "Plugins Path:" +msgstr "¿ãâì Ú ßÛÐÓØÝÐÜ:" + +#: gui/options.cpp:913 +msgid "Misc" +msgstr "ÀÐ×ÝÞÕ" + +#: gui/options.cpp:915 +msgid "Theme:" +msgstr "ÂÕÜÐ:" + +#: gui/options.cpp:919 +msgid "GUI Renderer:" +msgstr "ÀÐáâÕàØ×ÐâÞà GUI:" + +#: gui/options.cpp:925 +msgid "Autosave:" +msgstr "°ÒâÞáÞåàÐÝÕÝØÕ:" + +#: gui/options.cpp:933 +msgid "Keys" +msgstr "ºÛÐÒØèØ" + +#: gui/options.cpp:940 +msgid "GUI Language:" +msgstr "Ï×ëÚ ØÝâÕàäÕÙáÐ:" + +#: gui/options.cpp:940 +msgid "Language of ScummVM GUI" +msgstr "Ï×ëÚ ÓàÐäØçÕáÚÞÓÞ ØÝâÕàäÕÙáÐ ScummVM" + +#: gui/options.cpp:945 +msgid "English" +msgstr "English" + +#: gui/options.cpp:1089 +msgid "You have to restart ScummVM to take the effect." +msgstr "²ë ÔÞÛÖÝë ßÕàÕ×ÐßãáâØâì ScummVM çâÞÑë ßàØÜÕÝØâì Ø×ÜÕÝÕÝØï." + +#: gui/options.cpp:1102 +msgid "Select directory for savegames" +msgstr "²ëÑÕàØâÕ ÔØàÕÚâÞàØî ÔÛï áÞåàÐÝÕÝØÙ" + +#: gui/options.cpp:1109 +msgid "The chosen directory cannot be written to. Please select another one." +msgstr "½Õ ÜÞÓã ߨáÐâì Ò ÒëÑàÐÝÝãî ÔØàÕÚâÞàØî. ¿ÞÖÐÛãÙáâÐ, ãÚÐÖØâÕ ÔàãÓãî." + +#: gui/options.cpp:1118 +msgid "Select directory for GUI themes" +msgstr "²ëÑÕàØâÕ ÔØàÕÚâÞàØî ÔÛï âÕÜ GUI" + +#: gui/options.cpp:1128 +msgid "Select directory for extra files" +msgstr "²ëÑÕàØâÕ ÔØàÕÚâÞàØî á ÔÞßÞÛÝØâÕÛìÝëÜØ äÐÙÛÐÜØ" + +#: gui/options.cpp:1139 +msgid "Select directory for plugins" +msgstr "²ëÑÕàØâÕ ÔØàÕÚâÞàØî á ßÛÐÓØÝÐÜØ" + +#: gui/saveload.cpp:60 gui/saveload.cpp:241 +msgid "No date saved" +msgstr "´ÐâÐ ÝÕ ×ÐߨáÐÝÐ" + +#: gui/saveload.cpp:61 gui/saveload.cpp:242 +msgid "No time saved" +msgstr "²àÕÜï ÝÕ ×ÐߨáÐÝÞ" + +#: gui/saveload.cpp:62 gui/saveload.cpp:243 +msgid "No playtime saved" +msgstr "²àÕÜï ØÓàë ÝÕ ×ÐߨáÐÝÞ" + +#: gui/saveload.cpp:69 gui/saveload.cpp:157 +msgid "Delete" +msgstr "ÃÔÐÛØâì" + +#: gui/saveload.cpp:156 +msgid "Do you really want to delete this savegame?" +msgstr "²ë ÔÕÙáâÒØâÕÛìÝÞ åÞâØâÕ ãÔÐÛØâì íâÞ áÞåàÐÝÕÝØÕ?" + +#: gui/saveload.cpp:265 +msgid "Date: " +msgstr "´ÐâÐ: " + +#: gui/saveload.cpp:268 +msgid "Time: " +msgstr "²àÕÜï: " + +#: gui/saveload.cpp:273 +msgid "Playtime: " +msgstr "²àÕÜï ØÓàë: " + +#: gui/saveload.cpp:286 gui/saveload.cpp:353 +msgid "Untitled savestate" +msgstr "ÁÞåàÐÝÕÝØÕ ÑÕ× ØÜÕÝØ" + +#: gui/themebrowser.cpp:46 +msgid "Select a Theme" +msgstr "²ëÑÕàØâÕ âÕÜã" + +#: gui/ThemeEngine.cpp:337 +msgid "Disabled GFX" +msgstr "±Õ× ÓàÐäØÚØ" + +#: gui/ThemeEngine.cpp:338 +msgid "Standard Renderer (16bpp)" +msgstr "ÁâÐÝÔÐàâÝëÙ àÐáâÕàØ×ÐâÞà (16bpp)" + +#: gui/ThemeEngine.cpp:340 +msgid "Antialiased Renderer (16bpp)" +msgstr "ÀÐáâÕàØ×ÐâÞà áÞ áÓÛÐÖØÒÐÝØÕÜ (16bpp)" + +#: base/main.cpp:205 +#, c-format +msgid "Engine does not support debug level '%s'" +msgstr "´ÒØÖÞÚ ÝÕ ßÞÔÔÕàÖØÒÐÕâ ãàÞÒÕÝì ÞâÛÐÔÚØ '%s'" + +#: base/main.cpp:273 +msgid "Menu" +msgstr "¼ÕÝî" + +#: base/main.cpp:276 backends/platform/symbian/src/SymbianActions.cpp:48 +#: backends/platform/wince/CEActionsPocket.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:45 +msgid "Skip" +msgstr "¿àÞßãáâØâì" + +#: base/main.cpp:279 backends/platform/symbian/src/SymbianActions.cpp:53 +#: backends/platform/wince/CEActionsPocket.cpp:41 +msgid "Pause" +msgstr "¿Ðã×Ð" + +#: base/main.cpp:282 +msgid "Skip line" +msgstr "¿àÞßãáâØâì áâàÞÚã" + +#: base/main.cpp:404 +msgid "Error running game:" +msgstr "¾èØÑÚÐ ×ÐßãáÚÐ ØÓàë:" + +#: base/main.cpp:430 base/main.cpp:431 +msgid "Could not find any engine capable of running the selected game" +msgstr "½Õ ÜÞÓã ÝÐÙâØ ÔÒØÖÞÚ ÔÛï ×ÐßãáÚÐ ÒëÑàÐÝÝÞÙ ØÓàë" + +#: common/error.cpp:43 +msgid "Invalid Path" +msgstr "½ÕÒÕàÝëÙ ßãâì" + +#: common/error.cpp:44 +msgid "Game Data not found" +msgstr "½Õâ äÐÙÛÞÒ ØÓàë" + +#: common/error.cpp:45 +msgid "Game Id not supported" +msgstr "Game Id ÝÕ ßÞÔÔÕàÖØÒÐÕâáï" + +#: common/error.cpp:46 +msgid "Unsupported Color Mode" +msgstr "½ÕßÞÔÔÕàÖØÒÐÕÜëÙ àÕÖØÜ æÒÕâÐ" + +#: common/error.cpp:48 +msgid "Read permission denied" +msgstr "½ÕÔÞáâÐâÞçÝÞ ßàÐÒ ÔÛï çâÕÝØï" + +#: common/error.cpp:49 +msgid "Write permission denied" +msgstr "½ÕÔÞáâÐâÞçÝÞ ßàÐÒ ÔÛï ×ÐߨáØ" + +#: common/error.cpp:52 +msgid "Path not exists" +msgstr "¿ãâì ÝÕ ÝÐÙÔÕÝ" + +#: common/error.cpp:53 +msgid "Path not a directory" +msgstr "¿ãâì ÝÕ ïÒÛïÕâáï ÔØàÕÚâÞàØÕÙ" + +#: common/error.cpp:54 +msgid "Path not a file" +msgstr "¿ãâì ÝÕ ïÒÛïÕâáï äÐÙÛÞÜ" + +#: common/error.cpp:56 +msgid "Cannot create file" +msgstr "½Õ ÜÞÓã áÞ×ÔÐâì äÐÙÛ" + +#: common/error.cpp:57 +msgid "Reading failed" +msgstr "¾èØÑÚÐ çâÕÝØï" + +#: common/error.cpp:58 +msgid "Writing data failed" +msgstr "¾èØÑÚÐ ×ÐßØáØ ÔÐÝÝëå" + +#: common/error.cpp:60 common/error.cpp:71 +msgid "Unknown Error" +msgstr "½ÕØ×ÒÕáâÝÐï ÞèØÑÚÐ" + +#: common/util.cpp:254 +msgid "Hercules Green" +msgstr "Hercules ·ÕÛÕÝëÙ" + +#: common/util.cpp:255 +msgid "Hercules Amber" +msgstr "Hercules ÏÝâÐàÝëÙ" + +#: engines/dialogs.cpp:89 +msgid "~R~esume" +msgstr "¿àÞÔÞÛ~Ö~Øâì" + +#: engines/dialogs.cpp:91 +msgid "~L~oad" +msgstr "~·~ÐÓàãרâì" + +#: engines/dialogs.cpp:95 +msgid "~S~ave" +msgstr "~·~ÐߨáÐâì" + +#: engines/dialogs.cpp:99 +msgid "~O~ptions" +msgstr "~¾~ßæØØ" + +#: engines/dialogs.cpp:104 +msgid "~H~elp" +msgstr "~¿~ÞÜÞéì" + +#: engines/dialogs.cpp:107 +msgid "~A~bout" +msgstr "¾ ßàÞ~Ó~àÐÜÜÕ" + +#: engines/dialogs.cpp:109 +msgid "~R~eturn to Launcher" +msgstr "~²~ÕàÝãâìáï Ò ÓÛÐÒÝÞÕ ÜÕÝî" + +#: engines/dialogs.cpp:119 +msgid "Save game:" +msgstr "ÁÞåàÐÝØâì ØÓàã: " + +#: engines/dialogs.cpp:119 backends/platform/symbian/src/SymbianActions.cpp:47 +#: backends/platform/wince/CEActionsPocket.cpp:42 +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Save" +msgstr "·ÐߨáÐâì" + +#: engines/dialogs.cpp:301 engines/mohawk/dialogs.cpp:84 +#: engines/mohawk/dialogs.cpp:118 +msgid "~O~K" +msgstr "~O~K" + +#: engines/dialogs.cpp:302 engines/mohawk/dialogs.cpp:85 +#: engines/mohawk/dialogs.cpp:119 +msgid "~C~ancel" +msgstr "¾~â~ÜÕÝÐ" + +#: engines/dialogs.cpp:305 +msgid "~K~eys" +msgstr "~º~ÛÐÒØèØ" + +#: engines/scumm/dialogs.cpp:287 +msgid "~P~revious" +msgstr "~¿~àÕÔ" + +#: engines/scumm/dialogs.cpp:288 +msgid "~N~ext" +msgstr "~Á~ÛÕÔ" + +#: engines/scumm/dialogs.cpp:289 +#: backends/platform/ds/arm9/source/dsoptions.cpp:59 +msgid "~C~lose" +msgstr "~·~ÐÚàëâì" + +#: engines/mohawk/dialogs.cpp:81 engines/mohawk/dialogs.cpp:115 +msgid "~Z~ip Mode Activated" +msgstr "ÀÕÖØÜ ÑëáâàÞÓÞ ßÕàÕåÞÔÐ ÐÚâØÒØàÞÒÐÝ" + +#: engines/mohawk/dialogs.cpp:82 +msgid "~T~ransitions Enabled" +msgstr "¿ÕàÕåÞÔë ÐÚâØÒØàÞÒÐÝë" + +#: engines/mohawk/dialogs.cpp:116 +msgid "~W~ater Effect Enabled" +msgstr "ÍääÕÚâë ÒÞÔë ÒÚÛîçÕÝë" + +#: sound/fmopl.cpp:51 +msgid "MAME OPL emulator" +msgstr "ÍÜãÛïâÞà MAME OPL:" + +#: sound/fmopl.cpp:53 +msgid "DOSBox OPL emulator" +msgstr "ÍÜãÛïâÞà DOSBox OPL" + +#: sound/null.h:45 +msgid "No music" +msgstr "±Õ× Üã×ëÚØ" + +#: sound/softsynth/adlib.cpp:1590 +msgid "AdLib Emulator" +msgstr "ÍÜãÛïâÞà AdLib" + +#: sound/softsynth/mt32.cpp:327 +msgid "Initialising MT-32 Emulator" +msgstr "½ÐáâàÐØÒÐî íÜãÛïâÞà MT-32" + +#: sound/softsynth/mt32.cpp:541 +msgid "MT-32 Emulator" +msgstr "ÍÜãÛïâÞà MT-32" + +#: sound/softsynth/pcspk.cpp:142 +msgid "PC Speaker Emulator" +msgstr "ÍÜãÛïâÞà PC áߨÚÕàÐ" + +#: sound/softsynth/pcspk.cpp:161 +msgid "IBM PCjr Emulator" +msgstr "ÍÜãÛïâÞà IBM PCjr" + +#: sound/softsynth/ym2612.cpp:762 +msgid "FM Towns Emulator" +msgstr "ÍÜãÛïâÞà FM Towns" + +#: backends/keymapper/remap-dialog.cpp:49 +msgid "Keymap:" +msgstr "ÂÐÑÛØæÐ ÚÛÐÒØè:" + +#: backends/keymapper/remap-dialog.cpp:66 +msgid " (Active)" +msgstr " (°ÚâØÒÝÐï)" + +#: backends/keymapper/remap-dialog.cpp:100 +msgid " (Global)" +msgstr " (³ÛÞÑÐÛìÝÐï)" + +#: backends/keymapper/remap-dialog.cpp:110 +msgid " (Game)" +msgstr " (¸Óàë)" + +#: backends/midi/windows.cpp:157 +msgid "Windows MIDI" +msgstr "Windows MIDI" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:60 +msgid "ScummVM Main Menu" +msgstr "³ÛÐÒÝÞÕ ÜÕÝî ScummVM" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:66 +msgid "~L~eft handed mode" +msgstr "»ÕÒÞàãÚØÙ àÕÖØÜ" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:67 +msgid "~I~ndy fight controls" +msgstr "ÃßàÐÒÛÕÝØÕ ÑÞïÜØ Ò Indy" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:68 +msgid "Show mouse cursor" +msgstr "¿ÞÚÐ×ëÒÐâì ÚãàáÞà ÜëèØ" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:69 +msgid "Snap to edges" +msgstr "¿àØÚàÕߨâì Ú ÓàÐÝØæÐÜ" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:71 +msgid "Touch X Offset" +msgstr "ÁÜÕéÕÝØÕ ÚÐáÐÝØÙ ßÞ ÞáØ X" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:78 +msgid "Touch Y Offset" +msgstr "ÁÜÕéÕÝØÕ ÚÐáÐÝØÙ ßÞ ÞáØ Y" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:90 +msgid "Use laptop trackpad-style cursor control" +msgstr "¸áßÞÛì×ÞÒÐâì ãßàÐÒÛÕÝØÕ ÚãàáÞàÞÜ ÚÐÚ ÝÐ âàÕÚßÐÔÕ ÛÕßâÞßÞÒ" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:91 +msgid "Tap for left click, double tap right click" +msgstr "ÂÐß ÔÛï ÛÕÒÞÓÞ éÕÛçÚÐ, ÔÒÞÙÝÞÙ âÐß ÔÛï ßàÐÒÞÓÞ éÕÛçÚÐ" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:93 +msgid "Sensitivity" +msgstr "ÇãÒáâÒØâÕÛìÝÞáâì" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:102 +msgid "Initial top screen scale:" +msgstr "½ÐçÐÛìÝëÙ ÜÐáèâÐÑ ÒÕàåÝÕÓÞ íÚàÐÝÐ:" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:108 +msgid "Main screen scaling:" +msgstr "¼ÐáèâÐÑ ÓÛÐÒÝÞÓÞ íÚàÐÝÐ:" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:110 +msgid "Hardware scale (fast, but low quality)" +msgstr "ÅÐàÔÒÐàÝÞÕ ÜÐáèâÐÑØàÞÒÐÝØÕ (ÑëáâàÞ, ÝÞ ÝØ×ÚÞÓÞ ÚÐçÕáâÒÐ)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:111 +msgid "Software scale (good quality, but slower)" +msgstr "¿àÞÓàÐÜÜÝÞÕ ÜÐáèâÐÑØàÞÒÐÝØÕ (åÞàÞèÕÕ ÚÐçÕáâÒÞ, ÝÞ ÜÕÔÛÕÝÝÕÕ)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:112 +msgid "Unscaled (you must scroll left and right)" +msgstr "±Õ× ÜÐáèâÐÑØàÞÒÐÝØï (ÝãÖÝÞ ÑãÔÕâ ßàÞÚàãçØÒÐâì ÒÛÕÒÞ Ø ÒßàÐÒÞ)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:114 +msgid "Brightness:" +msgstr "ÏàÚÞáâì:" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:124 +msgid "High quality audio (slower) (reboot)" +msgstr "²ëáÞÚÞÕ ÚÐçÕáâÒÞ ×ÒãÚÐ (ÜÕÔÛÕÝÝÕÕ) (àÕÑãâ)" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:125 +msgid "Disable power off" +msgstr "·ÐßàÕâØâì ÒëÚÛîçÕÝØÕ" + +#: backends/platform/iphone/osys_events.cpp:339 +msgid "Touchpad mode enabled." +msgstr "ÀÕÖØÜ âÐçßÐÔÐ ÒÚÛîçÕÝ." + +#: backends/platform/iphone/osys_events.cpp:341 +msgid "Touchpad mode disabled." +msgstr "ÀÕÖØÜ âÐçßÐÔÐ ÒëÚÛîçÕÝ." + +#: backends/platform/sdl/graphics.cpp:40 +#: backends/platform/wince/wince-sdl.cpp:111 +#: backends/platform/wince/wince-sdl.cpp:118 +msgid "Normal (no scaling)" +msgstr "±Õ× ãÒÕÛØçÕÝØï" + +#: backends/platform/symbian/src/SymbianActions.cpp:41 +#: backends/platform/wince/CEActionsSmartphone.cpp:38 +msgid "Up" +msgstr "²ÒÕàå" + +#: backends/platform/symbian/src/SymbianActions.cpp:42 +#: backends/platform/wince/CEActionsSmartphone.cpp:39 +msgid "Down" +msgstr "²ÝØ×" + +#: backends/platform/symbian/src/SymbianActions.cpp:43 +#: backends/platform/wince/CEActionsSmartphone.cpp:40 +msgid "Left" +msgstr "²ÛÕÒÞ" + +#: backends/platform/symbian/src/SymbianActions.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:41 +msgid "Right" +msgstr "²ßàÐÒÞ" + +#: backends/platform/symbian/src/SymbianActions.cpp:45 +#: backends/platform/wince/CEActionsPocket.cpp:59 +#: backends/platform/wince/CEActionsSmartphone.cpp:42 +msgid "Left Click" +msgstr "»ÕÒëÙ éÕÛçÞÚ" + +#: backends/platform/symbian/src/SymbianActions.cpp:46 +#: backends/platform/wince/CEActionsSmartphone.cpp:43 +msgid "Right Click" +msgstr "¿àÐÒëÙ éÕÛçÞÚ" + +#: backends/platform/symbian/src/SymbianActions.cpp:49 +#: backends/platform/wince/CEActionsSmartphone.cpp:46 +msgid "Zone" +msgstr "·ÞÝÐ" + +#: backends/platform/symbian/src/SymbianActions.cpp:50 +#: backends/platform/wince/CEActionsPocket.cpp:53 +#: backends/platform/wince/CEActionsSmartphone.cpp:47 +msgid "Multi Function" +msgstr "¼ãÛìâØäãÝÚæØï" + +#: backends/platform/symbian/src/SymbianActions.cpp:51 +msgid "Swap character" +msgstr "ÁÜÕÝØâì ÓÕàÞï" + +#: backends/platform/symbian/src/SymbianActions.cpp:52 +msgid "Skip text" +msgstr "¿àÞßãáâØâì âÕÚáâ" + +#: backends/platform/symbian/src/SymbianActions.cpp:54 +msgid "Fast mode" +msgstr "±ëáâàëÙ àÕÖØÜ" + +#: backends/platform/symbian/src/SymbianActions.cpp:55 +#: backends/platform/wince/CEActionsPocket.cpp:43 +#: backends/platform/wince/CEActionsSmartphone.cpp:51 +msgid "Quit" +msgstr "²ëåÞÔ" + +#: backends/platform/symbian/src/SymbianActions.cpp:56 +msgid "Debugger" +msgstr "¾âÛÐÔçØÚ" + +#: backends/platform/symbian/src/SymbianActions.cpp:57 +msgid "Global menu" +msgstr "³ÛÞÑÐÛìÝÞÕ ÜÕÝî" + +#: backends/platform/symbian/src/SymbianActions.cpp:58 +msgid "Virtual keyboard" +msgstr "²ØàâãÐÛìÝÐï ÚÛÐÒØÐâãàÐ" + +#: backends/platform/symbian/src/SymbianActions.cpp:59 +msgid "Key mapper" +msgstr "½Ð×ÝÐçÕÝØÕ ÚÛÐÒØè" + +#: backends/platform/symbian/src/SymbianOS.cpp:446 +msgid "Do you want to quit ?" +msgstr "²ë åÞâØâÕ ÒëÙâØ?" + +#: backends/platform/wii/options.cpp:51 +msgid "Video" +msgstr "²ØÔÕÞ" + +#: backends/platform/wii/options.cpp:54 +msgid "Current video mode:" +msgstr "ÂÕÚãéØÙ ÒØÔÕÞàÕÖØÜ:" + +#: backends/platform/wii/options.cpp:56 +msgid "Double-strike" +msgstr "´ÒÞÙÝÞÙ ãÔÐà" + +#: backends/platform/wii/options.cpp:60 +msgid "Horizontal underscan:" +msgstr "³ÞàØ×ÞÝâÐÛìÝëÙ underscan:" + +#: backends/platform/wii/options.cpp:66 +msgid "Vertical underscan:" +msgstr "²ÕàâØÚÐÛìÝëÙ underscan:" + +#: backends/platform/wii/options.cpp:71 +msgid "Input" +msgstr "²ÒÞÔ" + +#: backends/platform/wii/options.cpp:74 +msgid "GC Pad sensitivity:" +msgstr "ÇãÒáâÐØâÕÛìÝÞáâì GC ßÐÔÐ:" + +#: backends/platform/wii/options.cpp:80 +msgid "GC Pad acceleration:" +msgstr "ÃáÚÞàÕÝØÕ GC ßÐÔÐ:" + +#: backends/platform/wii/options.cpp:86 +msgid "DVD" +msgstr "DVD" + +#: backends/platform/wii/options.cpp:89 backends/platform/wii/options.cpp:101 +msgid "Status:" +msgstr "ÁÞáâÞïÝØÕ:" + +#: backends/platform/wii/options.cpp:90 backends/platform/wii/options.cpp:102 +msgid "Unknown" +msgstr "½ÕØ×ÒÕáâÝÞ" + +#: backends/platform/wii/options.cpp:93 +msgid "Mount DVD" +msgstr "¿ÞÔÚÛîçØâì DVD" + +#: backends/platform/wii/options.cpp:94 +msgid "Unmount DVD" +msgstr "¾âÚÛîçØâì DVD" + +#: backends/platform/wii/options.cpp:98 +msgid "SMB" +msgstr "SMB" + +#: backends/platform/wii/options.cpp:106 +msgid "Server:" +msgstr "ÁÕàÒÕà:" + +#: backends/platform/wii/options.cpp:110 +msgid "Share:" +msgstr "ÁÕâÕÒÐï ßÐßÚÐ:" + +#: backends/platform/wii/options.cpp:114 +msgid "Username:" +msgstr "¿ÞÛì×ÞÒÐâÕÛì:" + +#: backends/platform/wii/options.cpp:118 +msgid "Password:" +msgstr "¿ÐàÞÛì:" + +#: backends/platform/wii/options.cpp:121 +msgid "Init network" +msgstr "¸ÝØæØÐÛØ×ÐæØï áÕâØ" + +#: backends/platform/wii/options.cpp:123 +msgid "Mount SMB" +msgstr "¿ÞÔÚÛîçØâì SMB" + +#: backends/platform/wii/options.cpp:124 +msgid "Unmount SMB" +msgstr "¾âÚÛîçâì SMB" + +#: backends/platform/wii/options.cpp:145 +msgid "DVD Mounted successfully" +msgstr "DVD ßÞÔÚÛîçÕÝ ãáßÕèÝÞ" + +#: backends/platform/wii/options.cpp:148 +msgid "Error while mounting the DVD" +msgstr "¾èØÑÚÐ ÒÞ ÒàÕÜï ßÞÔÚÛîçÕÝØï DVD" + +#: backends/platform/wii/options.cpp:150 +msgid "DVD not mounted" +msgstr "DVD ÝÕ ßÞÔÚÛîçÕÝ" + +#: backends/platform/wii/options.cpp:163 +msgid "Network up, share mounted" +msgstr "ÁÕâì àÐÑÞâÐÕâ, ßÐßÚÐ ßÞÔÚÛîçÕÝÐ" + +#: backends/platform/wii/options.cpp:165 +msgid "Network up" +msgstr "ÁÕâì àÐÑÞâÐÕâ" + +#: backends/platform/wii/options.cpp:168 +msgid ", error while mounting the share" +msgstr ", ÞèØÑÚÐ ÒÞ ÒàÕÜï ßÞÔÚÛîçÕÝØï ßÐßÚØ" + +#: backends/platform/wii/options.cpp:170 +msgid ", share not mounted" +msgstr ", ßÐßÚÐ ÝÕ ßÞÔÚÛîçÕÝÐ" + +#: backends/platform/wii/options.cpp:176 +msgid "Network down" +msgstr "ÁÕâì ÒëÚÛîçÕÝÐ" + +#: backends/platform/wii/options.cpp:180 +msgid "Initialising network" +msgstr "½ÐáâàÐØÒÐî áÕâì" + +#: backends/platform/wii/options.cpp:184 +msgid "Timeout while initialising network" +msgstr "²àÕÜï ßÞÔÚÛîçÕÝØï Ú áÕâØ ØáâÕÚÛÞ" + +#: backends/platform/wii/options.cpp:188 +#, c-format +msgid "Network not initialsed (%d)" +msgstr "ÁÕâì ÝÕ ÝÐáâàÞÕÝÐ (%d)" + +#: backends/platform/wince/CEActionsPocket.cpp:45 +msgid "Hide Toolbar" +msgstr "ÁßàïâÐâì ßÐÝÕÛì ØÝáâàãÜÕÝâÞÒ" + +#: backends/platform/wince/CEActionsPocket.cpp:46 +msgid "Show Keyboard" +msgstr "¿ÞÚÐ×Ðâì ÚÛÐÒØÐâãàã" + +#: backends/platform/wince/CEActionsPocket.cpp:47 +msgid "Sound on/off" +msgstr "·ÒãÚ ÒÚÛ/ÒëÚÛ" + +#: backends/platform/wince/CEActionsPocket.cpp:48 +msgid "Right click" +msgstr "¿àÐÒëÙ éÕÛçÞÚ" + +#: backends/platform/wince/CEActionsPocket.cpp:49 +msgid "Show/Hide Cursor" +msgstr "¿ÞÚÐ×Ðâì/ÃÑàÐâì ÚãàáÞà" + +#: backends/platform/wince/CEActionsPocket.cpp:50 +msgid "Free look" +msgstr "ÁÒÞÑÞÔÝëÙ ÞÑ×Þà" + +#: backends/platform/wince/CEActionsPocket.cpp:51 +msgid "Zoom up" +msgstr "ÃÒÕÛ. ÜÐáèâÐÑ" + +#: backends/platform/wince/CEActionsPocket.cpp:52 +msgid "Zoom down" +msgstr "ÃÜÕÝìè. ÜÐáèâÐÑ" + +#: backends/platform/wince/CEActionsPocket.cpp:54 +#: backends/platform/wince/CEActionsSmartphone.cpp:48 +msgid "Bind Keys" +msgstr "½Ð×ÝÐçØâì ÚÛÐÒØèØ" + +#: backends/platform/wince/CEActionsPocket.cpp:55 +msgid "Cursor Up" +msgstr "ºãàáÞà ÒÒÕàå" + +#: backends/platform/wince/CEActionsPocket.cpp:56 +msgid "Cursor Down" +msgstr "ºãàáÞà ÒÝØ×" + +#: backends/platform/wince/CEActionsPocket.cpp:57 +msgid "Cursor Left" +msgstr "ºãàáÞà ÒÛÕÒÞ" + +#: backends/platform/wince/CEActionsPocket.cpp:58 +msgid "Cursor Right" +msgstr "ºãàáÞà ÒßàÐÒÞ" + +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Do you want to load or save the game?" +msgstr "²ë åÞâØâÕ ×ÐÓàãרâì ÛØÑÞ áÞåàÐÝØâì ØÓàã?" + +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +msgid " Are you sure you want to quit ? " +msgstr " ²ë ãÒÕàÕÝë, çâÞ åÞâØâÕ ÒëÙâØ? " + +#: backends/platform/wince/CEActionsSmartphone.cpp:49 +msgid "Keyboard" +msgstr "ºÛÐÒØÐâãàÐ" + +#: backends/platform/wince/CEActionsSmartphone.cpp:50 +msgid "Rotate" +msgstr "¿ÞÒÕàÝãâì" + +#: backends/platform/wince/CELauncherDialog.cpp:58 +msgid "Using SDL driver " +msgstr "¸áßÞÛì×ãî ÔàÐÙÒÕà SDL " + +#: backends/platform/wince/CELauncherDialog.cpp:62 +msgid "Display " +msgstr "¿ÞÚÐ×Ðâì " + +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "Do you want to perform an automatic scan ?" +msgstr "²ë åÞâØâÕ ßàÞØ×ÒÕáâØ ÐÒâÞÜÐâØçÕáÚØÙ ßÞØáÚ?" diff --git a/po/scummvm.pot b/po/scummvm.pot new file mode 100644 index 0000000000..6fe4989982 --- /dev/null +++ b/po/scummvm.pot @@ -0,0 +1,1341 @@ +# LANGUAGE translation for ScummVM. +# Copyright (C) YEAR ScummVM Team +# This file is distributed under the same license as the ScummVM package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: ScummVM 1.2.0svn\n" +"Report-Msgid-Bugs-To: scummvm-devel@lists.sf.net\n" +"POT-Creation-Date: 2010-07-12 17:44+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: gui/about.cpp:96 +#, c-format +msgid "(built on %s)" +msgstr "" + +#: gui/about.cpp:103 +msgid "Features compiled in:" +msgstr "" + +#: gui/about.cpp:112 +msgid "Available engines:" +msgstr "" + +#: gui/browser.cpp:69 +msgid "Go up" +msgstr "" + +#: gui/browser.cpp:69 +msgid "Go to previous directory level" +msgstr "" + +#: gui/browser.cpp:70 gui/chooser.cpp:49 gui/KeysDialog.cpp:46 +#: gui/launcher.cpp:266 gui/massadd.cpp:95 gui/options.cpp:972 +#: gui/saveload.cpp:65 gui/saveload.cpp:157 gui/themebrowser.cpp:56 +#: backends/platform/wii/options.cpp:48 +msgid "Cancel" +msgstr "" + +#: gui/browser.cpp:71 gui/chooser.cpp:50 gui/themebrowser.cpp:57 +msgid "Choose" +msgstr "" + +#: gui/GuiManager.cpp:102 backends/keymapper/remap-dialog.cpp:54 +msgid "Close" +msgstr "" + +#: gui/GuiManager.cpp:105 +msgid "Mouse click" +msgstr "" + +#: gui/GuiManager.cpp:108 base/main.cpp:285 +msgid "Display keyboard" +msgstr "" + +#: gui/GuiManager.cpp:111 base/main.cpp:288 +msgid "Remap keys" +msgstr "" + +#: gui/KeysDialog.cpp:44 +msgid "Map" +msgstr "" + +#: gui/KeysDialog.cpp:45 gui/launcher.cpp:267 gui/launcher.cpp:873 +#: gui/launcher.cpp:877 gui/massadd.cpp:92 gui/options.cpp:973 +#: backends/platform/wii/options.cpp:47 +#: backends/platform/wince/CELauncherDialog.cpp:56 +msgid "OK" +msgstr "" + +#: gui/KeysDialog.cpp:52 +msgid "Select an action and click 'Map'" +msgstr "" + +#: gui/KeysDialog.cpp:83 gui/KeysDialog.cpp:105 gui/KeysDialog.cpp:144 +#, c-format +msgid "Associated key : %s" +msgstr "" + +#: gui/KeysDialog.cpp:85 gui/KeysDialog.cpp:107 gui/KeysDialog.cpp:146 +#, c-format +msgid "Associated key : none" +msgstr "" + +#: gui/KeysDialog.cpp:93 +msgid "Please select an action" +msgstr "" + +#: gui/KeysDialog.cpp:109 +msgid "Press the key to associate" +msgstr "" + +#: gui/KeysDialog.cpp:148 +msgid "Choose an action to map" +msgstr "" + +#: gui/launcher.cpp:170 +msgid "Game" +msgstr "" + +#: gui/launcher.cpp:173 +msgid "ID:" +msgstr "" + +#: gui/launcher.cpp:173 gui/launcher.cpp:174 +msgid "" +"Short game identifier used for referring to savegames and running the game " +"from the command line" +msgstr "" + +#: gui/launcher.cpp:177 +msgid "Name:" +msgstr "" + +#: gui/launcher.cpp:177 gui/launcher.cpp:178 +msgid "Full title of the game" +msgstr "" + +#: gui/launcher.cpp:181 +msgid "Language:" +msgstr "" + +#: gui/launcher.cpp:181 gui/launcher.cpp:182 +msgid "" +"Language of the game. This will not turn your Spanish game version into " +"English" +msgstr "" + +#: gui/launcher.cpp:183 gui/launcher.cpp:194 gui/options.cpp:80 +#: gui/options.cpp:617 gui/options.cpp:627 gui/options.cpp:943 +#: sound/null.cpp:42 +msgid "<default>" +msgstr "" + +#: gui/launcher.cpp:192 +msgid "Platform:" +msgstr "" + +#: gui/launcher.cpp:192 gui/launcher.cpp:193 +msgid "Platform the game was originally designed for" +msgstr "" + +#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867 +msgid "Graphics" +msgstr "" + +#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867 +msgid "GFX" +msgstr "" + +#: gui/launcher.cpp:206 +msgid "Override global graphic settings" +msgstr "" + +#: gui/launcher.cpp:213 gui/options.cpp:873 +msgid "Audio" +msgstr "" + +#: gui/launcher.cpp:215 +msgid "Override global audio settings" +msgstr "" + +#: gui/launcher.cpp:223 gui/options.cpp:877 +msgid "Volume" +msgstr "" + +#: gui/launcher.cpp:225 +msgid "Override global volume settings" +msgstr "" + +#: gui/launcher.cpp:232 gui/options.cpp:885 +msgid "MIDI" +msgstr "" + +#: gui/launcher.cpp:234 +msgid "Override global MIDI settings" +msgstr "" + +#: gui/launcher.cpp:244 gui/options.cpp:891 +msgid "Paths" +msgstr "" + +#: gui/launcher.cpp:250 +msgid "Game Path:" +msgstr "" + +#: gui/launcher.cpp:254 gui/options.cpp:904 +msgid "Extra Path:" +msgstr "" + +#: gui/launcher.cpp:254 gui/launcher.cpp:255 +msgid "Specifies path to additional data used the game" +msgstr "" + +#: gui/launcher.cpp:258 +msgid "Save Path:" +msgstr "" + +#: gui/launcher.cpp:258 gui/launcher.cpp:259 gui/options.cpp:898 +#: gui/options.cpp:899 +msgid "Specifies where your savegames are put" +msgstr "" + +#: gui/launcher.cpp:275 gui/launcher.cpp:353 gui/launcher.cpp:398 +#: gui/options.cpp:245 gui/options.cpp:400 gui/options.cpp:486 +#: gui/options.cpp:545 gui/options.cpp:706 gui/options.cpp:902 +#: gui/options.cpp:905 gui/options.cpp:909 gui/options.cpp:996 +#: gui/options.cpp:1002 gui/options.cpp:1008 gui/options.cpp:1016 +#: gui/options.cpp:1040 gui/options.cpp:1044 gui/options.cpp:1050 +#: gui/options.cpp:1057 gui/options.cpp:1156 +msgid "None" +msgstr "" + +#: gui/launcher.cpp:280 gui/launcher.cpp:357 +#: backends/platform/wii/options.cpp:56 +msgid "Default" +msgstr "" + +#: gui/launcher.cpp:391 gui/options.cpp:1150 +msgid "Select SoundFont" +msgstr "" + +#: gui/launcher.cpp:410 gui/launcher.cpp:548 +msgid "Select directory with game data" +msgstr "" + +#: gui/launcher.cpp:428 +msgid "Select additional game directory" +msgstr "" + +#: gui/launcher.cpp:440 +msgid "Select directory for saved games" +msgstr "" + +#: gui/launcher.cpp:459 +msgid "This game ID is already taken. Please choose another one." +msgstr "" + +#: gui/launcher.cpp:500 engines/dialogs.cpp:113 +msgid "~Q~uit" +msgstr "" + +#: gui/launcher.cpp:500 +msgid "Quit ScummVM" +msgstr "" + +#: gui/launcher.cpp:501 +msgid "A~b~out..." +msgstr "" + +#: gui/launcher.cpp:501 +msgid "About ScummVM" +msgstr "" + +#: gui/launcher.cpp:502 +msgid "~O~ptions..." +msgstr "" + +#: gui/launcher.cpp:502 +msgid "Change global ScummVM options" +msgstr "" + +#: gui/launcher.cpp:504 +msgid "~S~tart" +msgstr "" + +#: gui/launcher.cpp:504 +msgid "Start selected game" +msgstr "" + +#: gui/launcher.cpp:507 +msgid "~L~oad..." +msgstr "" + +#: gui/launcher.cpp:507 +msgid "Load savegame for selected game" +msgstr "" + +#: gui/launcher.cpp:511 +msgid "~A~dd Game..." +msgstr "" + +#: gui/launcher.cpp:511 +msgid "Hold Shift for Mass Add" +msgstr "" + +#: gui/launcher.cpp:513 +msgid "~E~dit Game..." +msgstr "" + +#: gui/launcher.cpp:513 +msgid "Change game options" +msgstr "" + +#: gui/launcher.cpp:515 +msgid "~R~emove Game" +msgstr "" + +#: gui/launcher.cpp:515 +msgid "Remove game from the list. The game data files stay intact" +msgstr "" + +#: gui/launcher.cpp:522 +msgid "Search in game list" +msgstr "" + +#: gui/launcher.cpp:526 gui/launcher.cpp:1037 +msgid "Search:" +msgstr "" + +#: gui/launcher.cpp:529 gui/options.cpp:707 +msgid "Clear value" +msgstr "" + +#: gui/launcher.cpp:551 engines/dialogs.cpp:117 +msgid "Load game:" +msgstr "" + +#: gui/launcher.cpp:551 engines/dialogs.cpp:117 +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Load" +msgstr "" + +#: gui/launcher.cpp:660 +msgid "" +"Do you really want to run the mass game detector? This could potentially add " +"a huge number of games." +msgstr "" + +#: gui/launcher.cpp:661 gui/launcher.cpp:810 +#: backends/platform/symbian/src/SymbianOS.cpp:446 +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "Yes" +msgstr "" + +#: gui/launcher.cpp:661 gui/launcher.cpp:810 +#: backends/platform/symbian/src/SymbianOS.cpp:446 +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "No" +msgstr "" + +#: gui/launcher.cpp:708 +msgid "ScummVM couldn't open the specified directory!" +msgstr "" + +#: gui/launcher.cpp:720 +msgid "ScummVM could not find any game in the specified directory!" +msgstr "" + +#: gui/launcher.cpp:734 +msgid "Pick the game:" +msgstr "" + +#: gui/launcher.cpp:810 +msgid "Do you really want to remove this game configuration?" +msgstr "" + +#: gui/launcher.cpp:873 +msgid "This game does not support loading games from the launcher." +msgstr "" + +#: gui/launcher.cpp:877 +msgid "ScummVM could not find any engine capable of running the selected game!" +msgstr "" + +#: gui/launcher.cpp:989 +msgid "Mass Add..." +msgstr "" + +#: gui/launcher.cpp:990 +msgid "Add Game..." +msgstr "" + +#: gui/massadd.cpp:79 gui/massadd.cpp:82 +msgid "... progress ..." +msgstr "" + +#: gui/massadd.cpp:244 +msgid "Scan complete!" +msgstr "" + +#: gui/massadd.cpp:247 +#, c-format +msgid "Discovered %d new games." +msgstr "" + +#: gui/massadd.cpp:251 +#, c-format +msgid "Scanned %d directories ..." +msgstr "" + +#: gui/massadd.cpp:254 +#, c-format +msgid "Discovered %d new games ..." +msgstr "" + +#: gui/options.cpp:78 +msgid "Never" +msgstr "" + +#: gui/options.cpp:78 +msgid "every 5 mins" +msgstr "" + +#: gui/options.cpp:78 +msgid "every 10 mins" +msgstr "" + +#: gui/options.cpp:78 +msgid "every 15 mins" +msgstr "" + +#: gui/options.cpp:78 +msgid "every 30 mins" +msgstr "" + +#: gui/options.cpp:80 +msgid "8 kHz" +msgstr "" + +#: gui/options.cpp:80 +msgid "11kHz" +msgstr "" + +#: gui/options.cpp:80 +msgid "22 kHz" +msgstr "" + +#: gui/options.cpp:80 +msgid "44 kHz" +msgstr "" + +#: gui/options.cpp:80 +msgid "48 kHz" +msgstr "" + +#: gui/options.cpp:614 +msgid "Graphics mode:" +msgstr "" + +#: gui/options.cpp:625 +msgid "Render mode:" +msgstr "" + +#: gui/options.cpp:625 gui/options.cpp:626 +msgid "Special dithering modes supported by some games" +msgstr "" + +#: gui/options.cpp:635 +msgid "Fullscreen mode" +msgstr "" + +#: gui/options.cpp:638 +msgid "Aspect ratio correction" +msgstr "" + +#: gui/options.cpp:638 +msgid "Correct aspect ratio for 320x200 games" +msgstr "" + +#: gui/options.cpp:645 +msgid "Preferred Device:" +msgstr "" + +#: gui/options.cpp:645 +msgid "Music Device:" +msgstr "" + +#: gui/options.cpp:645 +msgid "Specifies preferred sound device or sound card emulator" +msgstr "" + +#: gui/options.cpp:645 gui/options.cpp:646 +msgid "Specifies output sound device or sound card emulator" +msgstr "" + +#: gui/options.cpp:648 +msgid "MT-32 Device:" +msgstr "" + +#: gui/options.cpp:648 +msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output" +msgstr "" + +#: gui/options.cpp:650 +msgid "GM Device:" +msgstr "" + +#: gui/options.cpp:650 +msgid "Specifies default sound device for General MIDI output" +msgstr "" + +#: gui/options.cpp:682 +msgid "AdLib emulator:" +msgstr "" + +#: gui/options.cpp:682 gui/options.cpp:683 +msgid "AdLib is used for music in many games" +msgstr "" + +#: gui/options.cpp:693 +msgid "Output rate:" +msgstr "" + +#: gui/options.cpp:693 gui/options.cpp:694 +msgid "" +"Higher value specifies better sound quality but may be not supported by your " +"soundcard" +msgstr "" + +#: gui/options.cpp:705 +msgid "SoundFont:" +msgstr "" + +#: gui/options.cpp:705 gui/options.cpp:706 +msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity" +msgstr "" + +#: gui/options.cpp:710 +msgid "Mixed AdLib/MIDI mode" +msgstr "" + +#: gui/options.cpp:710 +msgid "Use both MIDI and AdLib sound generation" +msgstr "" + +#: gui/options.cpp:713 +msgid "True Roland MT-32 (disable GM emulation)" +msgstr "" + +#: gui/options.cpp:713 +msgid "" +"Check if you want to use your real hardware Roland-compatible sound device " +"connected to your computer" +msgstr "" + +#: gui/options.cpp:716 +msgid "Enable Roland GS Mode" +msgstr "" + +#: gui/options.cpp:716 +msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack" +msgstr "" + +#: gui/options.cpp:719 +msgid "MIDI gain:" +msgstr "" + +#: gui/options.cpp:732 +msgid "Text and Speech:" +msgstr "" + +#: gui/options.cpp:737 gui/options.cpp:743 +msgid "Speech" +msgstr "" + +#: gui/options.cpp:738 gui/options.cpp:744 +msgid "Subtitles" +msgstr "" + +#: gui/options.cpp:739 gui/options.cpp:745 +msgid "Both" +msgstr "" + +#: gui/options.cpp:743 +msgid "Spch" +msgstr "" + +#: gui/options.cpp:744 +msgid "Subs" +msgstr "" + +#: gui/options.cpp:745 +msgid "Show subtitles and play speech" +msgstr "" + +#: gui/options.cpp:749 +msgid "Subtitle speed:" +msgstr "" + +#: gui/options.cpp:761 +msgid "Music volume:" +msgstr "" + +#: gui/options.cpp:768 +msgid "Mute All" +msgstr "" + +#: gui/options.cpp:771 +msgid "SFX volume:" +msgstr "" + +#: gui/options.cpp:771 gui/options.cpp:772 +msgid "Special sound effects volume" +msgstr "" + +#: gui/options.cpp:778 +msgid "Speech volume:" +msgstr "" + +#: gui/options.cpp:898 +msgid "Save Path: " +msgstr "" + +#: gui/options.cpp:901 +msgid "Theme Path:" +msgstr "" + +#: gui/options.cpp:904 gui/options.cpp:905 +msgid "Specifies path to additional data used by all games or ScummVM" +msgstr "" + +#: gui/options.cpp:908 +msgid "Plugins Path:" +msgstr "" + +#: gui/options.cpp:913 +msgid "Misc" +msgstr "" + +#: gui/options.cpp:915 +msgid "Theme:" +msgstr "" + +#: gui/options.cpp:919 +msgid "GUI Renderer:" +msgstr "" + +#: gui/options.cpp:925 +msgid "Autosave:" +msgstr "" + +#: gui/options.cpp:933 +msgid "Keys" +msgstr "" + +#: gui/options.cpp:940 +msgid "GUI Language:" +msgstr "" + +#: gui/options.cpp:940 +msgid "Language of ScummVM GUI" +msgstr "" + +#: gui/options.cpp:945 +msgid "English" +msgstr "" + +#: gui/options.cpp:1089 +msgid "You have to restart ScummVM to take the effect." +msgstr "" + +#: gui/options.cpp:1102 +msgid "Select directory for savegames" +msgstr "" + +#: gui/options.cpp:1109 +msgid "The chosen directory cannot be written to. Please select another one." +msgstr "" + +#: gui/options.cpp:1118 +msgid "Select directory for GUI themes" +msgstr "" + +#: gui/options.cpp:1128 +msgid "Select directory for extra files" +msgstr "" + +#: gui/options.cpp:1139 +msgid "Select directory for plugins" +msgstr "" + +#: gui/saveload.cpp:60 gui/saveload.cpp:241 +msgid "No date saved" +msgstr "" + +#: gui/saveload.cpp:61 gui/saveload.cpp:242 +msgid "No time saved" +msgstr "" + +#: gui/saveload.cpp:62 gui/saveload.cpp:243 +msgid "No playtime saved" +msgstr "" + +#: gui/saveload.cpp:69 gui/saveload.cpp:157 +msgid "Delete" +msgstr "" + +#: gui/saveload.cpp:156 +msgid "Do you really want to delete this savegame?" +msgstr "" + +#: gui/saveload.cpp:265 +msgid "Date: " +msgstr "" + +#: gui/saveload.cpp:268 +msgid "Time: " +msgstr "" + +#: gui/saveload.cpp:273 +msgid "Playtime: " +msgstr "" + +#: gui/saveload.cpp:286 gui/saveload.cpp:353 +msgid "Untitled savestate" +msgstr "" + +#: gui/themebrowser.cpp:46 +msgid "Select a Theme" +msgstr "" + +#: gui/ThemeEngine.cpp:337 +msgid "Disabled GFX" +msgstr "" + +#: gui/ThemeEngine.cpp:338 +msgid "Standard Renderer (16bpp)" +msgstr "" + +#: gui/ThemeEngine.cpp:340 +msgid "Antialiased Renderer (16bpp)" +msgstr "" + +#: base/main.cpp:205 +#, c-format +msgid "Engine does not support debug level '%s'" +msgstr "" + +#: base/main.cpp:273 +msgid "Menu" +msgstr "" + +#: base/main.cpp:276 backends/platform/symbian/src/SymbianActions.cpp:48 +#: backends/platform/wince/CEActionsPocket.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:45 +msgid "Skip" +msgstr "" + +#: base/main.cpp:279 backends/platform/symbian/src/SymbianActions.cpp:53 +#: backends/platform/wince/CEActionsPocket.cpp:41 +msgid "Pause" +msgstr "" + +#: base/main.cpp:282 +msgid "Skip line" +msgstr "" + +#: base/main.cpp:404 +msgid "Error running game:" +msgstr "" + +#: base/main.cpp:430 base/main.cpp:431 +msgid "Could not find any engine capable of running the selected game" +msgstr "" + +#: common/error.cpp:43 +msgid "Invalid Path" +msgstr "" + +#: common/error.cpp:44 +msgid "Game Data not found" +msgstr "" + +#: common/error.cpp:45 +msgid "Game Id not supported" +msgstr "" + +#: common/error.cpp:46 +msgid "Unsupported Color Mode" +msgstr "" + +#: common/error.cpp:48 +msgid "Read permission denied" +msgstr "" + +#: common/error.cpp:49 +msgid "Write permission denied" +msgstr "" + +#: common/error.cpp:52 +msgid "Path not exists" +msgstr "" + +#: common/error.cpp:53 +msgid "Path not a directory" +msgstr "" + +#: common/error.cpp:54 +msgid "Path not a file" +msgstr "" + +#: common/error.cpp:56 +msgid "Cannot create file" +msgstr "" + +#: common/error.cpp:57 +msgid "Reading failed" +msgstr "" + +#: common/error.cpp:58 +msgid "Writing data failed" +msgstr "" + +#: common/error.cpp:60 common/error.cpp:71 +msgid "Unknown Error" +msgstr "" + +#: common/util.cpp:254 +msgid "Hercules Green" +msgstr "" + +#: common/util.cpp:255 +msgid "Hercules Amber" +msgstr "" + +#: engines/dialogs.cpp:89 +msgid "~R~esume" +msgstr "" + +#: engines/dialogs.cpp:91 +msgid "~L~oad" +msgstr "" + +#: engines/dialogs.cpp:95 +msgid "~S~ave" +msgstr "" + +#: engines/dialogs.cpp:99 +msgid "~O~ptions" +msgstr "" + +#: engines/dialogs.cpp:104 +msgid "~H~elp" +msgstr "" + +#: engines/dialogs.cpp:107 +msgid "~A~bout" +msgstr "" + +#: engines/dialogs.cpp:109 +msgid "~R~eturn to Launcher" +msgstr "" + +#: engines/dialogs.cpp:119 +msgid "Save game:" +msgstr "" + +#: engines/dialogs.cpp:119 backends/platform/symbian/src/SymbianActions.cpp:47 +#: backends/platform/wince/CEActionsPocket.cpp:42 +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Save" +msgstr "" + +#: engines/dialogs.cpp:301 engines/mohawk/dialogs.cpp:84 +#: engines/mohawk/dialogs.cpp:118 +msgid "~O~K" +msgstr "" + +#: engines/dialogs.cpp:302 engines/mohawk/dialogs.cpp:85 +#: engines/mohawk/dialogs.cpp:119 +msgid "~C~ancel" +msgstr "" + +#: engines/dialogs.cpp:305 +msgid "~K~eys" +msgstr "" + +#: engines/scumm/dialogs.cpp:287 +msgid "~P~revious" +msgstr "" + +#: engines/scumm/dialogs.cpp:288 +msgid "~N~ext" +msgstr "" + +#: engines/scumm/dialogs.cpp:289 +#: backends/platform/ds/arm9/source/dsoptions.cpp:59 +msgid "~C~lose" +msgstr "" + +#: engines/mohawk/dialogs.cpp:81 engines/mohawk/dialogs.cpp:115 +msgid "~Z~ip Mode Activated" +msgstr "" + +#: engines/mohawk/dialogs.cpp:82 +msgid "~T~ransitions Enabled" +msgstr "" + +#: engines/mohawk/dialogs.cpp:116 +msgid "~W~ater Effect Enabled" +msgstr "" + +#: sound/fmopl.cpp:51 +msgid "MAME OPL emulator" +msgstr "" + +#: sound/fmopl.cpp:53 +msgid "DOSBox OPL emulator" +msgstr "" + +#: sound/null.h:45 +msgid "No music" +msgstr "" + +#: sound/softsynth/adlib.cpp:1590 +msgid "AdLib Emulator" +msgstr "" + +#: sound/softsynth/mt32.cpp:327 +msgid "Initialising MT-32 Emulator" +msgstr "" + +#: sound/softsynth/mt32.cpp:541 +msgid "MT-32 Emulator" +msgstr "" + +#: sound/softsynth/pcspk.cpp:142 +msgid "PC Speaker Emulator" +msgstr "" + +#: sound/softsynth/pcspk.cpp:161 +msgid "IBM PCjr Emulator" +msgstr "" + +#: sound/softsynth/ym2612.cpp:762 +msgid "FM Towns Emulator" +msgstr "" + +#: backends/keymapper/remap-dialog.cpp:49 +msgid "Keymap:" +msgstr "" + +#: backends/keymapper/remap-dialog.cpp:66 +msgid " (Active)" +msgstr "" + +#: backends/keymapper/remap-dialog.cpp:100 +msgid " (Global)" +msgstr "" + +#: backends/keymapper/remap-dialog.cpp:110 +msgid " (Game)" +msgstr "" + +#: backends/midi/windows.cpp:157 +msgid "Windows MIDI" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:60 +msgid "ScummVM Main Menu" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:66 +msgid "~L~eft handed mode" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:67 +msgid "~I~ndy fight controls" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:68 +msgid "Show mouse cursor" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:69 +msgid "Snap to edges" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:71 +msgid "Touch X Offset" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:78 +msgid "Touch Y Offset" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:90 +msgid "Use laptop trackpad-style cursor control" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:91 +msgid "Tap for left click, double tap right click" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:93 +msgid "Sensitivity" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:102 +msgid "Initial top screen scale:" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:108 +msgid "Main screen scaling:" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:110 +msgid "Hardware scale (fast, but low quality)" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:111 +msgid "Software scale (good quality, but slower)" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:112 +msgid "Unscaled (you must scroll left and right)" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:114 +msgid "Brightness:" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:124 +msgid "High quality audio (slower) (reboot)" +msgstr "" + +#: backends/platform/ds/arm9/source/dsoptions.cpp:125 +msgid "Disable power off" +msgstr "" + +#: backends/platform/iphone/osys_events.cpp:339 +msgid "Touchpad mode enabled." +msgstr "" + +#: backends/platform/iphone/osys_events.cpp:341 +msgid "Touchpad mode disabled." +msgstr "" + +#: backends/platform/sdl/graphics.cpp:40 +#: backends/platform/wince/wince-sdl.cpp:111 +#: backends/platform/wince/wince-sdl.cpp:118 +msgid "Normal (no scaling)" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:41 +#: backends/platform/wince/CEActionsSmartphone.cpp:38 +msgid "Up" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:42 +#: backends/platform/wince/CEActionsSmartphone.cpp:39 +msgid "Down" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:43 +#: backends/platform/wince/CEActionsSmartphone.cpp:40 +msgid "Left" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:44 +#: backends/platform/wince/CEActionsSmartphone.cpp:41 +msgid "Right" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:45 +#: backends/platform/wince/CEActionsPocket.cpp:59 +#: backends/platform/wince/CEActionsSmartphone.cpp:42 +msgid "Left Click" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:46 +#: backends/platform/wince/CEActionsSmartphone.cpp:43 +msgid "Right Click" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:49 +#: backends/platform/wince/CEActionsSmartphone.cpp:46 +msgid "Zone" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:50 +#: backends/platform/wince/CEActionsPocket.cpp:53 +#: backends/platform/wince/CEActionsSmartphone.cpp:47 +msgid "Multi Function" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:51 +msgid "Swap character" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:52 +msgid "Skip text" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:54 +msgid "Fast mode" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:55 +#: backends/platform/wince/CEActionsPocket.cpp:43 +#: backends/platform/wince/CEActionsSmartphone.cpp:51 +msgid "Quit" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:56 +msgid "Debugger" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:57 +msgid "Global menu" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:58 +msgid "Virtual keyboard" +msgstr "" + +#: backends/platform/symbian/src/SymbianActions.cpp:59 +msgid "Key mapper" +msgstr "" + +#: backends/platform/symbian/src/SymbianOS.cpp:446 +msgid "Do you want to quit ?" +msgstr "" + +#: backends/platform/wii/options.cpp:51 +msgid "Video" +msgstr "" + +#: backends/platform/wii/options.cpp:54 +msgid "Current video mode:" +msgstr "" + +#: backends/platform/wii/options.cpp:56 +msgid "Double-strike" +msgstr "" + +#: backends/platform/wii/options.cpp:60 +msgid "Horizontal underscan:" +msgstr "" + +#: backends/platform/wii/options.cpp:66 +msgid "Vertical underscan:" +msgstr "" + +#: backends/platform/wii/options.cpp:71 +msgid "Input" +msgstr "" + +#: backends/platform/wii/options.cpp:74 +msgid "GC Pad sensitivity:" +msgstr "" + +#: backends/platform/wii/options.cpp:80 +msgid "GC Pad acceleration:" +msgstr "" + +#: backends/platform/wii/options.cpp:86 +msgid "DVD" +msgstr "" + +#: backends/platform/wii/options.cpp:89 backends/platform/wii/options.cpp:101 +msgid "Status:" +msgstr "" + +#: backends/platform/wii/options.cpp:90 backends/platform/wii/options.cpp:102 +msgid "Unknown" +msgstr "" + +#: backends/platform/wii/options.cpp:93 +msgid "Mount DVD" +msgstr "" + +#: backends/platform/wii/options.cpp:94 +msgid "Unmount DVD" +msgstr "" + +#: backends/platform/wii/options.cpp:98 +msgid "SMB" +msgstr "" + +#: backends/platform/wii/options.cpp:106 +msgid "Server:" +msgstr "" + +#: backends/platform/wii/options.cpp:110 +msgid "Share:" +msgstr "" + +#: backends/platform/wii/options.cpp:114 +msgid "Username:" +msgstr "" + +#: backends/platform/wii/options.cpp:118 +msgid "Password:" +msgstr "" + +#: backends/platform/wii/options.cpp:121 +msgid "Init network" +msgstr "" + +#: backends/platform/wii/options.cpp:123 +msgid "Mount SMB" +msgstr "" + +#: backends/platform/wii/options.cpp:124 +msgid "Unmount SMB" +msgstr "" + +#: backends/platform/wii/options.cpp:145 +msgid "DVD Mounted successfully" +msgstr "" + +#: backends/platform/wii/options.cpp:148 +msgid "Error while mounting the DVD" +msgstr "" + +#: backends/platform/wii/options.cpp:150 +msgid "DVD not mounted" +msgstr "" + +#: backends/platform/wii/options.cpp:163 +msgid "Network up, share mounted" +msgstr "" + +#: backends/platform/wii/options.cpp:165 +msgid "Network up" +msgstr "" + +#: backends/platform/wii/options.cpp:168 +msgid ", error while mounting the share" +msgstr "" + +#: backends/platform/wii/options.cpp:170 +msgid ", share not mounted" +msgstr "" + +#: backends/platform/wii/options.cpp:176 +msgid "Network down" +msgstr "" + +#: backends/platform/wii/options.cpp:180 +msgid "Initialising network" +msgstr "" + +#: backends/platform/wii/options.cpp:184 +msgid "Timeout while initialising network" +msgstr "" + +#: backends/platform/wii/options.cpp:188 +#, c-format +msgid "Network not initialsed (%d)" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:45 +msgid "Hide Toolbar" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:46 +msgid "Show Keyboard" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:47 +msgid "Sound on/off" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:48 +msgid "Right click" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:49 +msgid "Show/Hide Cursor" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:50 +msgid "Free look" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:51 +msgid "Zoom up" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:52 +msgid "Zoom down" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:54 +#: backends/platform/wince/CEActionsSmartphone.cpp:48 +msgid "Bind Keys" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:55 +msgid "Cursor Up" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:56 +msgid "Cursor Down" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:57 +msgid "Cursor Left" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:58 +msgid "Cursor Right" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:263 +#: backends/platform/wince/CEActionsSmartphone.cpp:225 +msgid "Do you want to load or save the game?" +msgstr "" + +#: backends/platform/wince/CEActionsPocket.cpp:313 +#: backends/platform/wince/CEActionsSmartphone.cpp:272 +msgid " Are you sure you want to quit ? " +msgstr "" + +#: backends/platform/wince/CEActionsSmartphone.cpp:49 +msgid "Keyboard" +msgstr "" + +#: backends/platform/wince/CEActionsSmartphone.cpp:50 +msgid "Rotate" +msgstr "" + +#: backends/platform/wince/CELauncherDialog.cpp:58 +msgid "Using SDL driver " +msgstr "" + +#: backends/platform/wince/CELauncherDialog.cpp:62 +msgid "Display " +msgstr "" + +#: backends/platform/wince/CELauncherDialog.cpp:104 +msgid "Do you want to perform an automatic scan ?" +msgstr "" @@ -65,8 +65,9 @@ endif ldid -S scummvm chmod 755 scummvm cp scummvm $(bundle_name)/ScummVM - cp $(srcdir)/dists/iphone/icon.png $(bundle_name)/icon.png - cp $(srcdir)/dists/iphone/Default.png $(bundle_name)/Default.png + cp $(srcdir)/dists/iphone/icon.png $(bundle_name)/ + cp $(srcdir)/dists/iphone/icon-72.png $(bundle_name)/ + cp $(srcdir)/dists/iphone/Default.png $(bundle_name)/ # Location of static libs for the iPhone ifneq ($(BACKEND), iphone) @@ -101,6 +102,10 @@ ifdef USE_ZLIB OSX_ZLIB ?= -lz endif +ifdef USE_TERMCONV +OSX_ICONV ?= -liconv +endif + # Special target to create a static linked binary for Mac OS X. # We use -force_cpusubtype_ALL to ensure the binary runs on every # PowerPC machine. @@ -109,6 +114,7 @@ scummvm-static: $(OBJS) -framework CoreMIDI \ $(OSX_STATIC_LIBS) \ $(OSX_ZLIB) \ + $(OSX_ICONV) \ -lSystemStubs # Special target to create a static linked binary for the iPhone diff --git a/sound/audiostream.cpp b/sound/audiostream.cpp index ce2c521e5e..a092e6c29d 100644 --- a/sound/audiostream.cpp +++ b/sound/audiostream.cpp @@ -95,6 +95,12 @@ SeekableAudioStream *SeekableAudioStream::openStreamFile(const Common::String &b LoopingAudioStream::LoopingAudioStream(RewindableAudioStream *stream, uint loops, DisposeAfterUse::Flag disposeAfterUse) : _parent(stream), _disposeAfterUse(disposeAfterUse), _loops(loops), _completeIterations(0) { + assert(stream); + + if (!stream->rewind()) { + // TODO: Properly indicate error + _loops = _completeIterations = 1; + } } LoopingAudioStream::~LoopingAudioStream() { diff --git a/sound/audiostream.h b/sound/audiostream.h index 37a1953bb9..64ad128931 100644 --- a/sound/audiostream.h +++ b/sound/audiostream.h @@ -109,6 +109,9 @@ public: /** * Creates a looping audio stream object. * + * Note that on creation of the LoopingAudioStream object + * the underlying stream will be rewound. + * * @see makeLoopingAudioStream * * @param stream Stream to loop @@ -126,6 +129,7 @@ public: /** * Returns number of loops the stream has played. + * * @param numLoops number of loops to play, 0 - infinite */ uint getCompleteIterations() const { return _completeIterations; } @@ -145,8 +149,8 @@ private: * overhead down, when the code does not require any functionality only offered * by LoopingAudioStream. * - * @param stream Stream to loop (will be automatically destroyed, when the looping is done) - * @param loops How often to loop (0 = infinite) + * @param stream Stream to loop (will be automatically destroyed, when the looping is done) + * @param loops How often to loop (0 = infinite) * @return A new AudioStream, which offers the desired functionality. */ AudioStream *makeLoopingAudioStream(RewindableAudioStream *stream, uint loops); @@ -162,7 +166,8 @@ public: * Tries to load a file by trying all available formats. * In case of an error, the file handle will be closed, but deleting * it is still the responsibility of the caller. - * @param basename a filename without an extension + * + * @param basename a filename without an extension * @return an SeekableAudioStream ready to use in case of success; * NULL in case of an error (e.g. invalid/nonexisting file) */ @@ -208,9 +213,9 @@ public: * by LoopingAudioStream. * * @param stream Stream to loop (will be automatically destroyed, when the looping is done) - * @param start Starttime of the stream interval to be looped - * @param end End of the stream interval to be looped (a zero time, means till end) - * @param loops How often to loop (0 = infinite) + * @param start Starttime of the stream interval to be looped + * @param end End of the stream interval to be looped (a zero time, means till end) + * @param loops How often to loop (0 = infinite) * @return A new AudioStream, which offers the desired functionality. */ AudioStream *makeLoopingAudioStream(SeekableAudioStream *stream, Timestamp start, Timestamp end, uint loops); @@ -232,10 +237,13 @@ public: /** * Constructor for a SubLoopingAudioStream. * - * @param stream Stream to loop - * @param loops How often the stream should be looped (0 means infinite) - * @param loopStart Start of the loop (this must be smaller than loopEnd) - * @param loopEnd End of the loop (thus must be greater than loopStart) + * Note that on creation of the SubLoopingAudioStream object + * the underlying stream will be rewound. + * + * @param stream Stream to loop + * @param loops How often the stream should be looped (0 means infinite) + * @param loopStart Start of the loop (this must be smaller than loopEnd) + * @param loopEnd End of the loop (thus must be greater than loopStart) * @param disposeAfterUse Whether the stream should be disposed, when the * SubLoopingAudioStream is destroyed. */ @@ -279,9 +287,9 @@ public: /** * Creates a new SubSeekableAudioStream. * - * @param parent parent stream object. - * @param start Start time. - * @param end End time. + * @param parent parent stream object. + * @param start Start time. + * @param end End time. * @param disposeAfterUse Whether the parent stream object should be destroyed on destruction of the SubSeekableAudioStream. */ SubSeekableAudioStream(SeekableAudioStream *parent, const Timestamp start, const Timestamp end, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES); @@ -317,7 +325,7 @@ public: * contained in it has been played. */ virtual void queueAudioStream(Audio::AudioStream *audStream, - DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) = 0; + DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES) = 0; /** * Queue a block of raw audio data for playback. This stream plays all @@ -327,10 +335,10 @@ public: * * @note Make sure to allocate the data block with malloc(), not with new[]. * - * @param data pointer to the audio data block - * @param size length of the audio data block - * @param disposeAfterUse if equal to DisposeAfterUse::YES, the block is released using free() after use. - * @param flags a bit-ORed combination of RawFlags describing the audio data format + * @param data pointer to the audio data block + * @param size length of the audio data block + * @param disposeAfterUse if equal to DisposeAfterUse::YES, the block is released using free() after use. + * @param flags a bit-ORed combination of RawFlags describing the audio data format */ void queueBuffer(byte *data, uint32 size, DisposeAfterUse::Flag disposeAfterUse, byte flags); @@ -357,8 +365,8 @@ QueuingAudioStream *makeQueuingAudioStream(int rate, bool stereo); * Converts a point in time to a precise sample offset * with the given parameters. * - * @param where Point in time. - * @param rate Rate of the stream. + * @param where Point in time. + * @param rate Rate of the stream. * @param isStereo Is the stream a stereo stream? */ Timestamp convertTimeToStreamPos(const Timestamp &where, int rate, bool isStereo); diff --git a/sound/decoders/adpcm.h b/sound/decoders/adpcm.h index 7452478f35..04dbb1a521 100644 --- a/sound/decoders/adpcm.h +++ b/sound/decoders/adpcm.h @@ -71,7 +71,7 @@ enum typesADPCM { * @param rate the sampling rate * @param channels the number of channels * @param blockAlign block alignment ??? - * @return a new RewindableAudioStream, or NULL, if an error occured + * @return a new RewindableAudioStream, or NULL, if an error occurred */ RewindableAudioStream *makeADPCMStream( Common::SeekableReadStream *stream, diff --git a/sound/decoders/aiff.cpp b/sound/decoders/aiff.cpp index 2f12669072..b76410f8d1 100644 --- a/sound/decoders/aiff.cpp +++ b/sound/decoders/aiff.cpp @@ -161,16 +161,21 @@ bool loadAIFFFromStream(Common::SeekableReadStream &stream, int &size, int &rate return true; } -SeekableAudioStream *makeAIFFStream(Common::SeekableReadStream &stream) { +SeekableAudioStream *makeAIFFStream(Common::SeekableReadStream *stream, + DisposeAfterUse::Flag disposeAfterUse) { int size, rate; byte *data, flags; - if (!loadAIFFFromStream(stream, size, rate, flags)) + if (!loadAIFFFromStream(*stream, size, rate, flags)) { + if (disposeAfterUse == DisposeAfterUse::YES) + delete stream; return 0; + } data = (byte *)malloc(size); assert(data); - stream.read(data, size); + stream->read(data, size); + delete stream; // Since we allocated our own buffer for the data, we must specify DisposeAfterUse::YES. return makeRawStream(data, size, rate, flags); diff --git a/sound/decoders/aiff.h b/sound/decoders/aiff.h index e8a3b6f0b0..53f86c95fd 100644 --- a/sound/decoders/aiff.h +++ b/sound/decoders/aiff.h @@ -34,6 +34,7 @@ #define SOUND_AIFF_H #include "common/scummsys.h" +#include "common/types.h" namespace Common { class SeekableReadStream; } @@ -55,8 +56,14 @@ extern bool loadAIFFFromStream(Common::SeekableReadStream &stream, int &size, in * from that data. * * This function uses loadAIFFFromStream() internally. + * + * @param stream the SeekableReadStream from which to read the AIFF data + * @param disposeAfterUse whether to delete the stream after use + * @return a new SeekableAudioStream, or NULL, if an error occurred */ -SeekableAudioStream *makeAIFFStream(Common::SeekableReadStream &stream); +SeekableAudioStream *makeAIFFStream( + Common::SeekableReadStream *stream, + DisposeAfterUse::Flag disposeAfterUse); } // End of namespace Audio diff --git a/sound/decoders/flac.cpp b/sound/decoders/flac.cpp index fb9499e31f..2a92735616 100644 --- a/sound/decoders/flac.cpp +++ b/sound/decoders/flac.cpp @@ -229,7 +229,7 @@ FLACStream::FLACStream(Common::SeekableReadStream *inStream, bool dispose) if (processUntilEndOfMetadata() && _streaminfo.channels > 0) { _lastSample = _streaminfo.total_samples + 1; _length = Timestamp(0, _lastSample - 1, getRate()); - return; // no error occured + return; // no error occurred } } @@ -354,7 +354,7 @@ int FLACStream::readBuffer(int16 *buffer, const int numSamples) { break; default: decoderOk = false; - warning("FLACStream: An error occured while decoding. DecoderState is: %s", + warning("FLACStream: An error occurred while decoding. DecoderState is: %s", FLAC__StreamDecoderStateString[getStreamDecoderState()]); } @@ -667,7 +667,7 @@ inline void FLACStream::callbackMetadata(const ::FLAC__StreamMetadata *metadata) } inline void FLACStream::callbackError(::FLAC__StreamDecoderErrorStatus status) { // some of these are non-critical-Errors - debug(1, "FLACStream: An error occured while decoding. DecoderState is: %s", + debug(1, "FLACStream: An error occurred while decoding. DecoderState is: %s", FLAC__StreamDecoderErrorStatusString[status]); } diff --git a/sound/decoders/flac.h b/sound/decoders/flac.h index 982450c045..3c00ec3d5d 100644 --- a/sound/decoders/flac.h +++ b/sound/decoders/flac.h @@ -41,8 +41,8 @@ #ifndef SOUND_FLAC_H #define SOUND_FLAC_H -#include "common/types.h" #include "common/scummsys.h" +#include "common/types.h" #ifdef USE_FLAC @@ -61,7 +61,7 @@ class SeekableAudioStream; * * @param stream the SeekableReadStream from which to read the FLAC data * @param disposeAfterUse whether to delete the stream after use - * @return a new SeekableAudioStream, or NULL, if an error occured + * @return a new SeekableAudioStream, or NULL, if an error occurred */ SeekableAudioStream *makeFLACStream( Common::SeekableReadStream *stream, diff --git a/sound/decoders/mp3.h b/sound/decoders/mp3.h index 3175df5e92..ed54c8b013 100644 --- a/sound/decoders/mp3.h +++ b/sound/decoders/mp3.h @@ -41,8 +41,8 @@ #ifndef SOUND_MP3_H #define SOUND_MP3_H -#include "common/types.h" #include "common/scummsys.h" +#include "common/types.h" #ifdef USE_MAD @@ -61,7 +61,7 @@ class SeekableAudioStream; * * @param stream the SeekableReadStream from which to read the MP3 data * @param disposeAfterUse whether to delete the stream after use - * @return a new SeekableAudioStream, or NULL, if an error occured + * @return a new SeekableAudioStream, or NULL, if an error occurred */ SeekableAudioStream *makeMP3Stream( Common::SeekableReadStream *stream, diff --git a/sound/decoders/vag.h b/sound/decoders/vag.h index 7e0ed255be..cdf91a8ea1 100644 --- a/sound/decoders/vag.h +++ b/sound/decoders/vag.h @@ -49,7 +49,7 @@ class RewindableAudioStream; * * @param stream the SeekableReadStream from which to read the ADPCM data * @param rate the sampling rate - * @return a new RewindableAudioStream, or NULL, if an error occured + * @return a new RewindableAudioStream, or NULL, if an error occurred */ RewindableAudioStream *makeVagStream( Common::SeekableReadStream *stream, diff --git a/sound/decoders/voc.h b/sound/decoders/voc.h index 79956ee62a..82cc261f2c 100644 --- a/sound/decoders/voc.h +++ b/sound/decoders/voc.h @@ -38,8 +38,8 @@ #ifndef SOUND_VOC_H #define SOUND_VOC_H -#include "common/types.h" #include "common/scummsys.h" +#include "common/types.h" namespace Common { class ReadStream; } namespace Common { class SeekableReadStream; } diff --git a/sound/decoders/vorbis.cpp b/sound/decoders/vorbis.cpp index a8ac7784f5..5aeb40c139 100644 --- a/sound/decoders/vorbis.cpp +++ b/sound/decoders/vorbis.cpp @@ -34,7 +34,7 @@ #include "sound/audiostream.h" #ifdef USE_TREMOR -#if defined(ANDROID) || defined(__GP32__) // custom libtremor locations +#if defined(__GP32__) // custom libtremor locations #include <ivorbisfile.h> #else #include <tremor/ivorbisfile.h> diff --git a/sound/decoders/vorbis.h b/sound/decoders/vorbis.h index dd0a89bfdd..0a0cf43bc9 100644 --- a/sound/decoders/vorbis.h +++ b/sound/decoders/vorbis.h @@ -41,8 +41,8 @@ #ifndef SOUND_VORBIS_H #define SOUND_VORBIS_H -#include "common/types.h" #include "common/scummsys.h" +#include "common/types.h" #ifdef USE_VORBIS @@ -61,7 +61,7 @@ class SeekableAudioStream; * * @param stream the SeekableReadStream from which to read the Ogg Vorbis data * @param disposeAfterUse whether to delete the stream after use - * @return a new SeekableAudioStream, or NULL, if an error occured + * @return a new SeekableAudioStream, or NULL, if an error occurred */ SeekableAudioStream *makeVorbisStream( Common::SeekableReadStream *stream, diff --git a/sound/decoders/wave.h b/sound/decoders/wave.h index f0e3bb249b..edd37e7ac9 100644 --- a/sound/decoders/wave.h +++ b/sound/decoders/wave.h @@ -38,8 +38,8 @@ #ifndef SOUND_WAVE_H #define SOUND_WAVE_H -#include "common/types.h" #include "common/scummsys.h" +#include "common/types.h" namespace Common { class SeekableReadStream; } @@ -71,7 +71,7 @@ extern bool loadWAVFromStream( * * @param stream the SeekableReadStream from which to read the WAVE data * @param disposeAfterUse whether to delete the stream after use - * @return a new RewindableAudioStream, or NULL, if an error occured + * @return a new RewindableAudioStream, or NULL, if an error occurred */ RewindableAudioStream *makeWAVStream( Common::SeekableReadStream *stream, diff --git a/sound/fmopl.cpp b/sound/fmopl.cpp index 8fdddc20f8..16dc3986d6 100644 --- a/sound/fmopl.cpp +++ b/sound/fmopl.cpp @@ -28,6 +28,7 @@ #include "sound/softsynth/opl/mame.h" #include "common/config-manager.h" +#include "common/translation.h" namespace OPL { @@ -47,9 +48,9 @@ OPL::OPL() { const Config::EmulatorDescription Config::_drivers[] = { { "auto", "<default>", kAuto, kFlagOpl2 | kFlagDualOpl2 | kFlagOpl3 }, - { "mame", "MAME OPL emulator", kMame, kFlagOpl2 }, + { "mame", _s("MAME OPL emulator"), kMame, kFlagOpl2 }, #ifndef DISABLE_DOSBOX_OPL - { "db", "DOSBox OPL emulator", kDOSBox, kFlagOpl2 | kFlagDualOpl2 | kFlagOpl3 }, + { "db", _s("DOSBox OPL emulator"), kDOSBox, kFlagOpl2 | kFlagDualOpl2 | kFlagOpl3 }, #endif { 0, 0, 0, 0 } }; diff --git a/sound/mididrv.cpp b/sound/mididrv.cpp index a9a782184e..aaff78bf92 100644 --- a/sound/mididrv.cpp +++ b/sound/mididrv.cpp @@ -29,72 +29,8 @@ #include "common/system.h" #include "common/util.h" #include "sound/mididrv.h" - -/** Internal list of all available 'midi' drivers. */ -static const MidiDriverDescription s_musicDrivers[] = { - - // The flags for the "auto" & "null" drivers indicate that they are anything - // you want it to be. - {"auto", "<default>", MD_AUTO, MDT_MIDI | MDT_PCSPK | MDT_ADLIB | MDT_TOWNS}, - {"null", "No music", MD_NULL, MDT_MIDI | MDT_PCSPK | MDT_ADLIB | MDT_TOWNS}, - -#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) - {"windows", "Windows MIDI", MD_WINDOWS, MDT_MIDI}, -#endif - -#if defined(UNIX) && defined(USE_ALSA) - {"alsa", "ALSA", MD_ALSA, MDT_MIDI}, -#endif - -#if defined(__MINT__) - {"stmidi", "Atari ST MIDI", MD_STMIDI, MDT_MIDI}, -#endif - -#if defined(UNIX) && !defined(__BEOS__) && !defined(MACOSX) && !defined(__MAEMO__) && !defined(__MINT__) - {"seq", "SEQ", MD_SEQ, MDT_MIDI}, -#endif - -#if defined(IRIX) - {"dmedia", "DMedia", MD_DMEDIA, MDT_MIDI}, -#endif - -#if defined(__amigaos4__) - {"camd", "CAMD", MD_CAMD, MDT_MIDI}, -#endif - -#if defined(MACOSX) - {"core", "CoreAudio", MD_COREAUDIO, MDT_MIDI}, -// {"coreaudio", "CoreAudio", MD_COREAUDIO, MDT_MIDI}, - {"coremidi", "CoreMIDI", MD_COREMIDI, MDT_MIDI}, -#endif - -#if defined(PALMOS_MODE) -# if defined(COMPILE_CLIE) - {"ypa1", "Yamaha Pa1", MD_YPA1, MDT_MIDI}, -# elif defined(COMPILE_ZODIAC) && (!defined(ENABLE_SCUMM) || !defined(PALMOS_ARM)) - {"zodiac", "Tapwave Zodiac", MD_ZODIAC, MDT_MIDI}, -# endif -#endif - -#ifdef USE_FLUIDSYNTH - {"fluidsynth", "FluidSynth", MD_FLUIDSYNTH, MDT_MIDI}, -#endif -#ifdef USE_MT32EMU - {"mt32", "MT-32 Emulation", MD_MT32, MDT_MIDI}, -#endif - - // The flags for the "adlib" driver indicates that it can do AdLib and MIDI. - {"adlib", "AdLib", MD_ADLIB, MDT_ADLIB}, - {"pcspk", "PC Speaker", MD_PCSPK, MDT_PCSPK}, - {"pcjr", "IBM PCjr", MD_PCJR, MDT_PCSPK}, - {"cms", "Creative Music System", MD_CMS, MDT_CMS}, - {"towns", "FM Towns", MD_TOWNS, MDT_TOWNS}, -#if defined(UNIX) - {"timidity", "TiMidity", MD_TIMIDITY, MDT_MIDI}, -#endif - - {0, 0, MD_NULL, MDT_NONE} -}; +#include "sound/musicplugin.h" +#include "common/translation.h" const byte MidiDriver::_mt32ToGm[128] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F @@ -120,169 +56,221 @@ const byte MidiDriver::_gmToMt32[128] = { 101, 103, 100, 120, 117, 113, 99, 128, 128, 128, 128, 124, 123, 128, 128, 128, // 7x }; -const MidiDriverDescription *MidiDriver::getAvailableMidiDrivers() { - return s_musicDrivers; -} +static const uint32 GUIOMapping[] = { + MT_PCSPK, Common::GUIO_MIDIPCSPK, + /*MDT_CMS, Common::GUIO_MIDICMS,*/ + MT_PCJR, Common::GUIO_MIDIPCJR, + MT_ADLIB, Common::GUIO_MIDIADLIB, + MT_TOWNS, Common::GUIO_MIDITOWNS, + MT_GM, Common::GUIO_MIDIGM, + MT_MT32, Common::GUIO_MIDIMT32, + 0, 0 +}; -const MidiDriverDescription *MidiDriver::findMusicDriver(const Common::String &str) { - if (str.empty()) - return 0; +uint32 MidiDriver::musicType2GUIO(uint32 musicType) { + uint32 res = 0; + + for (int i = 0; GUIOMapping[i] || GUIOMapping[i + 1]; i += 2) { + if (musicType == GUIOMapping[i] || musicType == (uint32)-1) + res |= GUIOMapping[i + 1]; + } + + return res; +} - const char *s = str.c_str(); - int len = 0; - const MidiDriverDescription *md = s_musicDrivers; +bool MidiDriver::_forceTypeMT32 = false; - // Scan for string end or a colon - while (s[len] != 0 && s[len] != ':') - len++; +MusicType MidiDriver::getMusicType(MidiDriver::DeviceHandle handle) { + if (_forceTypeMT32) + return MT_MT32; - while (md->name) { - // Compare the string passed to us with the current table entry. - // We ignore any characters following an (optional) colon ':' - // contained in str. - if (!scumm_strnicmp(md->name, s, len)) { - return md; + if (handle) { + const MusicPlugin::List p = MusicMan.getPlugins(); + for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) { + MusicDevices i = (**m)->getDevices(); + for (MusicDevices::iterator d = i.begin(); d != i.end(); d++) { + if (handle == d->getHandle()) + return d->getMusicType(); + } } - md++; } - - return 0; + + return MT_INVALID; } -static MidiDriverType getDefaultMIDIDriver() { -#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) - return MD_WINDOWS; -#elif defined(MACOSX) - return MD_COREAUDIO; -#elif defined(PALMOS_MODE) - #if defined(COMPILE_CLIE) - return MD_YPA1; - #elif defined(COMPILE_ZODIAC) - return MD_ZODIAC; - #else - return MD_NULL; - #endif -#else - return MD_NULL; -#endif -} +Common::String MidiDriver::getDeviceString(DeviceHandle handle, DeviceStringType type) { + if (handle) { + const MusicPlugin::List p = MusicMan.getPlugins(); + for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) { + MusicDevices i = (**m)->getDevices(); + for (MusicDevices::iterator d = i.begin(); d != i.end(); d++) { + if (handle == d->getHandle()) { + if (type == kDriverName) + return d->getMusicDriverName(); + else if (type == kDriverId) + return d->getMusicDriverId(); + else if (type == kDeviceId) + return d->getCompleteId(); + else + return Common::String("auto"); + } + } + } + } -MidiDriverType MidiDriver::parseMusicDriver(const Common::String &str) { - const MidiDriverDescription *md = findMusicDriver(str); - if (md) - return md->id; - return MD_AUTO; + return Common::String("auto"); } -MidiDriverType MidiDriver::detectMusicDriver(int flags) { - MidiDriverType musicDriver; +MidiDriver::DeviceHandle MidiDriver::detectDevice(int flags) { + // Query the selected music device (defaults to MT_AUTO device). + DeviceHandle hdl = getDeviceHandle(ConfMan.get("music_driver")); - // Query the selected music driver (defaults to MD_AUTO). - const MidiDriverDescription *md = findMusicDriver(ConfMan.get("music_driver")); + _forceTypeMT32 = false; // Check whether the selected music driver is compatible with the // given flags. - if (!md || !(md->flags & flags)) - musicDriver = MD_AUTO; - else - musicDriver = md->id; - - // If the selected driver is MD_AUTO, we try to determine - // a suitable and "optimal" music driver. - if (musicDriver == MD_AUTO) { - - if (flags & MDT_PREFER_MIDI) { - // A MIDI music driver is preferred. Of course this implies - // that MIDI is actually listed in flags, so we verify that. - assert(flags & MDT_MIDI); - - // Query the default MIDI driver. It's possible that there - // is none, in which case we revert to AUTO mode. - musicDriver = getDefaultMIDIDriver(); - if (musicDriver == MD_NULL) - musicDriver = MD_AUTO; - } + switch (getMusicType(hdl)) { + case MT_PCSPK: + if (flags & MDT_PCSPK) + return hdl; + break; + + case MT_PCJR: + if (flags & MDT_PCJR) + return hdl; + break; + + case MT_CMS: + if (flags & MDT_CMS) + return hdl; + break; + + case MT_ADLIB: + if (flags & MDT_ADLIB) + return hdl; + break; + + case MT_TOWNS: + if (flags & MDT_TOWNS) + return hdl; + break; + + case MT_PC98: + if (flags & MDT_PC98) + return hdl; + break; + + case MT_GM: + case MT_GS: + case MT_MT32: + if (flags & MDT_MIDI) + return hdl; + break; + + case MT_NULL: + return hdl; - if (musicDriver == MD_AUTO) { - // MIDI is not preferred, or no default MIDI device is available. - // In this case we first try the alternate drivers before checking - // for a 'real' MIDI driver. - - if (flags & MDT_TOWNS) - musicDriver = MD_TOWNS; - else if (flags & MDT_ADLIB) - musicDriver = MD_ADLIB; - else if (flags & MDT_PCSPK) - musicDriver = MD_PCJR; - else if (flags & MDT_MIDI) - musicDriver = getDefaultMIDIDriver(); + default: + break; + } + + // If the selected driver did not match the flags setting, + // we try to determine a suitable and "optimal" music driver. + const MusicPlugin::List p = MusicMan.getPlugins(); + // If only MDT_MIDI but not MDT_PREFER_MT32 or MDT_PREFER_GM is set we prefer the other devices (which will always be + // detected since they are hard coded and cannot be disabled. + for (int l = (flags & (MDT_PREFER_GM | MDT_PREFER_MT32)) ? 1 : 0; l < 2; ++l) { + if ((flags & MDT_MIDI) && (l == 1)) { + // If a preferred MT32 or GM device has been selected that device gets returned + if (flags & MDT_PREFER_MT32) + hdl = getDeviceHandle(ConfMan.get("mt32_device")); + else if (flags & MDT_PREFER_GM) + hdl = getDeviceHandle(ConfMan.get("gm_device")); else - musicDriver = MD_NULL; + hdl = getDeviceHandle("auto"); + + const MusicType type = getMusicType(hdl); + if (type != MT_AUTO && type != MT_INVALID) { + if (flags & MDT_PREFER_MT32) + // If we have a preferred MT32 device we disable the gm/mt32 mapping (more about this in mididrv.h) + _forceTypeMT32 = true; + + return hdl; + } + + // If we have no specific device selected (neither in the scummvm nor in the game domain) + // and no preferred MT32 or GM device selected we arrive here. + // If MT32 is preferred we try for the first available device with music type 'MT_MT32' (usually the mt32 emulator) + if (flags & MDT_PREFER_MT32) { + for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { + MusicDevices i = (**m)->getDevices(); + for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { + if (d->getMusicType() == MT_MT32) + return d->getHandle(); + } + } + } + + // Now we default to the first available device with music type 'MT_GM' + for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { + MusicDevices i = (**m)->getDevices(); + for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { + if (d->getMusicType() == MT_GM || d->getMusicType() == MT_GS) + return d->getHandle(); + } + } + } + + MusicType tp = MT_AUTO; + if (flags & MDT_TOWNS) + tp = MT_TOWNS; + else if (flags & MDT_ADLIB) + tp = MT_ADLIB; + else if (flags & MDT_PCSPK) + tp = MT_PCSPK; + else if (l == 0) + // if we haven't tried to find a MIDI device yet we do this now. + continue; + else + tp = MT_AUTO; + + for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); ++m) { + MusicDevices i = (**m)->getDevices(); + for (MusicDevices::iterator d = i.begin(); d != i.end(); ++d) { + if (d->getMusicType() == tp) + return d->getHandle(); + } } } - return musicDriver; + return 0; } -MidiDriver *MidiDriver::createMidi(MidiDriverType midiDriver) { - switch (midiDriver) { - case MD_NULL: return MidiDriver_NULL_create(); - - case MD_ADLIB: return MidiDriver_ADLIB_create(); - - case MD_TOWNS: return MidiDriver_YM2612_create(); - - // Right now PC Speaker and PCjr are handled - // outside the MidiDriver architecture, so - // don't create anything for now. - case MD_PCSPK: - case MD_CMS: - case MD_PCJR: return NULL; - -#ifdef USE_FLUIDSYNTH - case MD_FLUIDSYNTH: return MidiDriver_FluidSynth_create(); -#endif - -#ifdef USE_MT32EMU - case MD_MT32: return MidiDriver_MT32_create(); -#endif - -#if defined(PALMOS_MODE) -#if defined(COMPILE_CLIE) - case MD_YPA1: return MidiDriver_YamahaPa1_create(); -#elif defined(COMPILE_ZODIAC) && (!defined(ENABLE_SCUMM) || !defined(PALMOS_ARM)) - case MD_ZODIAC: return MidiDriver_Zodiac_create(); -#endif -#endif - -#if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) - case MD_WINDOWS: return MidiDriver_WIN_create(); -#endif -#if defined(__MINT__) - case MD_STMIDI: return MidiDriver_STMIDI_create(); -#endif -#if defined(UNIX) && !defined(__BEOS__) && !defined(MACOSX) && !defined(__MAEMO__) && !defined(__MINT__) - case MD_SEQ: return MidiDriver_SEQ_create(); -#endif -#if defined(UNIX) - case MD_TIMIDITY: return MidiDriver_TIMIDITY_create(); -#endif -#if defined(IRIX) - case MD_DMEDIA: return MidiDriver_DMEDIA_create(); -#endif -#if defined(MACOSX) - case MD_COREAUDIO: return MidiDriver_CORE_create(); - case MD_COREMIDI: return MidiDriver_CoreMIDI_create(); -#endif -#if defined(UNIX) && defined(USE_ALSA) - case MD_ALSA: return MidiDriver_ALSA_create(); -#endif -#if defined(__amigaos4__) - case MD_CAMD: return MidiDriver_CAMD_create(); -#endif - default: - error("Invalid midi driver selected"); +MidiDriver *MidiDriver::createMidi(MidiDriver::DeviceHandle handle) { + MidiDriver *driver = 0; + const MusicPlugin::List p = MusicMan.getPlugins(); + for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) { + if (getDeviceString(handle, MidiDriver::kDriverId).equals((**m)->getId())) + (**m)->createInstance(&driver, handle); + } + + return driver; +} + +MidiDriver::DeviceHandle MidiDriver::getDeviceHandle(const Common::String &identifier) { + const MusicPlugin::List p = MusicMan.getPlugins(); + + if (p.begin() == p.end()) + error("Music plugins must be loaded prior to calling this method."); + + for (MusicPlugin::List::const_iterator m = p.begin(); m != p.end(); m++) { + MusicDevices i = (**m)->getDevices(); + for (MusicDevices::iterator d = i.begin(); d != i.end(); d++) { + if (identifier.equals(d->getCompleteId()) || identifier.equals(d->getCompleteName())) { + return d->getHandle(); + } + } } - return NULL; + return 0; } diff --git a/sound/mididrv.h b/sound/mididrv.h index d7e89dd9ca..5fffd430fb 100644 --- a/sound/mididrv.h +++ b/sound/mididrv.h @@ -30,6 +30,8 @@ #include "common/timer.h" class MidiChannel; +class MusicDevice; + namespace Audio { class Mixer; } @@ -43,56 +45,32 @@ namespace Common { class String; } * * @todo Rename MidiDriverType to MusicDriverType */ -enum MidiDriverType { - // Pseudo drivers - MD_AUTO, - MD_NULL, - - // Windows - MD_WINDOWS, - - // Atari ST - MD_STMIDI, - - // Linux - MD_ALSA, - MD_SEQ, - - // Mac OS X - MD_QTMUSIC, - MD_COREAUDIO, - MD_COREMIDI, - - // PalmOS - MD_YPA1, - MD_ZODIAC, - - // IRIX - MD_DMEDIA, - - // AMIGAOS4 - MD_CAMD, - - // MIDI softsynths - MD_FLUIDSYNTH, - MD_MT32, - - // "Fake" MIDI devices - MD_ADLIB, - MD_PCSPK, - MD_CMS, - MD_PCJR, - MD_TOWNS, - MD_TIMIDITY + +/** + * Music types that music drivers can implement and engines can rely on. + */ +enum MusicType { + MT_INVALID = -1, // Invalid output + MT_AUTO = 0, // Auto + MT_NULL, // Null + MT_PCSPK, // PC Speaker + MT_PCJR, // PCjr + MT_CMS, // CMS + MT_ADLIB, // AdLib + MT_TOWNS, // FM-TOWNS + MT_PC98, // PC98 + MT_GM, // General MIDI + MT_MT32, // MT-32 + MT_GS // Roland GS }; /** - * A set of flags to be passed to detectMusicDriver() which can be used to + * A set of flags to be passed to detectDevice() which can be used to * specify what kind of music driver is preferred / accepted. * - * The flags (except for MDT_PREFER_MIDI) indicate whether a given driver + * The flags (except for MDT_PREFER_MT32 and MDT_PREFER_GM) indicate whether a given driver * type is acceptable. E.g. the TOWNS music driver could be returned by - * detectMusicDriver if and only if MDT_TOWNS is specified. + * detectDevice if and only if MDT_TOWNS is specified. * * @todo Rename MidiDriverFlags to MusicDriverFlags */ @@ -100,10 +78,13 @@ enum MidiDriverFlags { MDT_NONE = 0, MDT_PCSPK = 1 << 0, // PC Speaker: Maps to MD_PCSPK and MD_PCJR MDT_CMS = 1 << 1, // Creative Music System / Gameblaster: Maps to MD_CMS - MDT_ADLIB = 1 << 2, // AdLib: Maps to MD_ADLIB - MDT_TOWNS = 1 << 3, // FM-TOWNS: Maps to MD_TOWNS - MDT_MIDI = 1 << 4, // Real MIDI - MDT_PREFER_MIDI = 1 << 5 // Real MIDI output is preferred + MDT_PCJR = 1 << 2, // Tandy/PC Junior driver + MDT_ADLIB = 1 << 3, // AdLib: Maps to MT_ADLIB + MDT_TOWNS = 1 << 4, // FM-TOWNS: Maps to MT_TOWNS + MDT_PC98 = 1 << 5, // FM-TOWNS: Maps to MT_PC98 + MDT_MIDI = 1 << 6, // Real MIDI + MDT_PREFER_MT32 = 1 << 7, // MT-32 output is preferred + MDT_PREFER_GM = 1 << 8 // GM output is preferred }; /** @@ -113,12 +94,6 @@ enum MidiDriverFlags { * * @todo Rename MidiDriverType to MusicDriverType */ -struct MidiDriverDescription { - const char *name; - const char *description; - MidiDriverType id; // A unique ID for each driver - int flags; // Capabilities of this driver -}; /** * Abstract MIDI Driver Class @@ -127,22 +102,45 @@ struct MidiDriverDescription { */ class MidiDriver { public: - /** Find the music driver matching the given driver name/description. */ - static const MidiDriverDescription *findMusicDriver(const Common::String &str); - - /** Get the id of the music driver matching the given driver name, or MD_AUTO if there is no match. */ - static MidiDriverType parseMusicDriver(const Common::String &str); - /** - * Get a list of all available MidiDriver types. - * @return list of all available midi drivers, terminated by a zero entry + * The device handle. + * + * The value 0 is reserved for an invalid device for now. + * TODO: Maybe we should use -1 (i.e. 0xFFFFFFFF) as + * invalid device? */ - static const MidiDriverDescription *getAvailableMidiDrivers(); + typedef uint32 DeviceHandle; - static MidiDriver *createMidi(MidiDriverType midiDriver); + enum DeviceStringType { + kDriverName, + kDriverId, + kDeviceId + }; - static MidiDriverType detectMusicDriver(int flags); + static uint32 musicType2GUIO(uint32 musicType); + /** Create music driver matching the given device handle, or NULL if there is no match. */ + static MidiDriver *createMidi(DeviceHandle handle); + + /** Returns device handle based on the present devices and the flags parameter. */ + static DeviceHandle detectDevice(int flags); + + /** Find the music driver matching the given driver name/description. */ + static DeviceHandle getDeviceHandle(const Common::String &identifier); + + /** Get the music type matching the given device handle, or MT_AUTO if there is no match. */ + static MusicType getMusicType(DeviceHandle handle); + + /** Get the device description string matching the given device handle and the given type. */ + static Common::String getDeviceString(DeviceHandle handle, DeviceStringType type); + +private: + // If detectDevice() detects MT32 and we have a preferred MT32 device + // we use this to force getMusicType() to return MT_MT32 so that we don't + // have to rely on the 'True Roland MT-32' config manager setting (since nobody + // would possibly think about activating 'True Roland MT-32' when he has set + // 'Music Driver' to '<default>') + static bool _forceTypeMT32; public: virtual ~MidiDriver() { } @@ -271,28 +269,4 @@ public: virtual void sysEx_customInstrument(uint32 type, const byte *instr) = 0; }; - -// Factory functions, for faster compile -extern MidiDriver *MidiDriver_NULL_create(); -extern MidiDriver *MidiDriver_ADLIB_create(); -extern MidiDriver *MidiDriver_WIN_create(); -extern MidiDriver *MidiDriver_STMIDI_create(); -extern MidiDriver *MidiDriver_SEQ_create(); -extern MidiDriver *MidiDriver_TIMIDITY_create(); -extern MidiDriver *MidiDriver_QT_create(); -extern MidiDriver *MidiDriver_CORE_create(); -extern MidiDriver *MidiDriver_CoreMIDI_create(); -extern MidiDriver *MidiDriver_ALSA_create(); -extern MidiDriver *MidiDriver_DMEDIA_create(); -extern MidiDriver *MidiDriver_CAMD_create(); -extern MidiDriver *MidiDriver_YM2612_create(); -#ifdef USE_FLUIDSYNTH -extern MidiDriver *MidiDriver_FluidSynth_create(); -#endif -#ifdef USE_MT32EMU -extern MidiDriver *MidiDriver_MT32_create(); -#endif -extern MidiDriver *MidiDriver_YamahaPa1_create(); -extern MidiDriver *MidiDriver_Zodiac_create(); - #endif diff --git a/sound/midiparser.cpp b/sound/midiparser.cpp index 8ae2bad71a..d58471765e 100644 --- a/sound/midiparser.cpp +++ b/sound/midiparser.cpp @@ -67,6 +67,10 @@ void MidiParser::property(int prop, int value) { } } +void MidiParser::sendToDriver(uint32 b) { + _driver->send(b); +} + void MidiParser::setTempo(uint32 tempo) { _tempo = tempo; if (_ppqn) @@ -127,7 +131,7 @@ void MidiParser::hangingNote(byte channel, byte note, uint32 time_left, bool rec best = ptr; if (ptr->time_left) { if (recycle) - _driver->send(0x80 | channel, note, 0); + sendToDriver(0x80 | channel, note, 0); --_hanging_notes_count; } break; @@ -172,7 +176,7 @@ void MidiParser::onTimer() { for (i = ARRAYSIZE(_hanging_notes); i; --i, ++ptr) { if (ptr->time_left) { if (ptr->time_left <= _timer_rate) { - _driver->send(0x80 | ptr->channel, ptr->note, 0); + sendToDriver(0x80 | ptr->channel, ptr->note, 0); ptr->time_left = 0; --_hanging_notes_count; } else { @@ -232,7 +236,7 @@ void MidiParser::onTimer() { else activeNote(info.channel(), info.basic.param1, true); } - _driver->send(info.event, info.basic.param1, info.basic.param2); + sendToDriver(info.event, info.basic.param1, info.basic.param2); } @@ -258,7 +262,7 @@ void MidiParser::allNotesOff() { for (i = 0; i < 128; ++i) { for (j = 0; j < 16; ++j) { if (_active_notes[i] & (1 << j)) { - _driver->send(0x80 | j, i, 0); + sendToDriver(0x80 | j, i, 0); } } } @@ -266,7 +270,7 @@ void MidiParser::allNotesOff() { // Turn off all hanging notes for (i = 0; i < ARRAYSIZE(_hanging_notes); i++) { if (_hanging_notes[i].time_left) { - _driver->send(0x80 | _hanging_notes[i].channel, _hanging_notes[i].note, 0); + sendToDriver(0x80 | _hanging_notes[i].channel, _hanging_notes[i].note, 0); _hanging_notes[i].time_left = 0; } } @@ -276,7 +280,7 @@ void MidiParser::allNotesOff() { // support this...). for (i = 0; i < 16; ++i) { - _driver->send(0xB0 | i, 0x7b, 0); // All notes off + sendToDriver(0xB0 | i, 0x7b, 0); // All notes off } memset(_active_notes, 0, sizeof(_active_notes)); @@ -348,7 +352,7 @@ void MidiParser::hangAllActiveNotes() { for (j = 0; j < 16; ++j) { if (temp_active[i] & (1 << j)) { activeNote(j, i, false); - _driver->send(0x80 | j, i, 0); + sendToDriver(0x80 | j, i, 0); } } } @@ -399,7 +403,7 @@ bool MidiParser::jumpToTick(uint32 tick, bool fireEvents, bool stopNotes) { else _driver->sysEx(info.ext.data, (uint16)info.length); } else - _driver->send(info.event, info.basic.param1, info.basic.param2); + sendToDriver(info.event, info.basic.param1, info.basic.param2); } parseNextEvent(_next_event); @@ -441,7 +445,7 @@ void MidiParser::unloadMusic() { if (_driver) { for (int i = 0; i < 16; ++i) { - _driver->send(0xE0 | i, 0, 0x40); + sendToDriver(0xE0 | i, 0, 0x40); } } } diff --git a/sound/midiparser.h b/sound/midiparser.h index 0ba12ce2b1..3ef99fcd6e 100644 --- a/sound/midiparser.h +++ b/sound/midiparser.h @@ -267,13 +267,12 @@ struct NoteTimer { * memory block containing the music data.) */ class MidiParser { -private: +protected: uint16 _active_notes[128]; ///< Each uint16 is a bit mask for channels that have that note on. NoteTimer _hanging_notes[32]; ///< Maintains expiration info for up to 32 notes. ///< Used for "Smart Jump" and MIDI formats that do not include explicit Note Off events. byte _hanging_notes_count; ///< Count of hanging notes, used to optimize expiration. -protected: MidiDriver *_driver; ///< The device to which all events will be transmitted. uint32 _timer_rate; ///< The time in microseconds between onTimer() calls. Obtained from the MidiDriver. uint32 _ppqn; ///< Pulses Per Quarter Note. (We refer to "pulses" as "ticks".) @@ -303,6 +302,11 @@ protected: void hangingNote(byte channel, byte note, uint32 ticks_left, bool recycle = true); void hangAllActiveNotes(); + virtual void sendToDriver(uint32 b); + void sendToDriver(byte status, byte firstOp, byte secondOp) { + sendToDriver(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16)); + } + /** * Platform independent BE uint32 read-and-advance. * This helper function reads Big Endian 32-bit numbers diff --git a/sound/mods/protracker.h b/sound/mods/protracker.h index dfcb0e6c51..af722637c7 100644 --- a/sound/mods/protracker.h +++ b/sound/mods/protracker.h @@ -48,7 +48,7 @@ class AudioStream; * @param stream the ReadStream from which to read the ProTracker data * @param rate TODO * @param stereo TODO - * @return a new AudioStream, or NULL, if an error occured + * @return a new AudioStream, or NULL, if an error occurred */ AudioStream *makeProtrackerStream(Common::SeekableReadStream *stream, int offs = 0, int rate = 44100, bool stereo = true); diff --git a/sound/musicplugin.cpp b/sound/musicplugin.cpp index b4754230da..8078094616 100644 --- a/sound/musicplugin.cpp +++ b/sound/musicplugin.cpp @@ -24,10 +24,12 @@ */ #include "sound/musicplugin.h" +#include "common/hash-str.h" +#include "common/translation.h" MusicDevice::MusicDevice(MusicPluginObject const *musicPlugin, Common::String name, MusicType mt) : - _musicDriverName(musicPlugin->getName()), _musicDriverId(musicPlugin->getId()), - _name(name), _type(mt) { + _musicDriverName(_(musicPlugin->getName())), _musicDriverId(musicPlugin->getId()), + _name(_(name)), _type(mt) { } Common::String MusicDevice::getCompleteName() { @@ -46,3 +48,17 @@ Common::String MusicDevice::getCompleteName() { return name; } + +Common::String MusicDevice::getCompleteId() { + Common::String id = _musicDriverId; + if (!_name.empty()) { + id += "_"; + id += _name; + } + + return id; +} + +MidiDriver::DeviceHandle MusicDevice::getHandle() { + return (MidiDriver::DeviceHandle)Common::hashit(getCompleteId().c_str()); +} diff --git a/sound/musicplugin.h b/sound/musicplugin.h index df97494a90..3823f2fd3d 100644 --- a/sound/musicplugin.h +++ b/sound/musicplugin.h @@ -29,19 +29,6 @@ #include "sound/mididrv.h" #include "common/list.h" -/** - * Music types that music drivers can implement and engines can rely on. - */ -enum MusicType { - MT_PCSPK = 1, // PC Speaker - MT_PCJR = 2, // PCjr - MT_ADLIB = 3, // AdLib - MT_TOWNS = 4, // FM-TOWNS - MT_GM = 5, // General MIDI - MT_MT32 = 6, // MT-32 - MT_GS = 7 // Roland GS -}; - class MusicPluginObject; /** @@ -63,6 +50,14 @@ public: * device name (if it isn't the default one) and the name of the driver. */ Common::String getCompleteName(); + + /** + * Returns a user readable string that contains the name of the current + * device name (if it isn't the default one) and the id of the driver. + */ + Common::String getCompleteId(); + + MidiDriver::DeviceHandle getHandle(); private: Common::String _name; @@ -94,15 +89,18 @@ public: virtual MusicDevices getDevices() const = 0; /** - * Tries to instantiate a MIDI Driver instance based on the settings of - * the currently active ConfMan target. That is, the MusicPluginObject - * should query the ConfMan singleton for the device name, port, etc. + * Tries to instantiate a MIDI Driver instance based on the device + * previously detected via MidiDriver::detectDevice() * * @param mididriver Pointer to a pointer which the MusicPluginObject sets * to the newly create MidiDriver, or 0 in case of an error + * + * @param dev Pointer to a device to be used then creating the driver instance. + * Default value of zero for driver types without devices. + * * @return a Common::Error describing the error which occurred, or kNoError */ - virtual Common::Error createInstance(MidiDriver **mididriver) const = 0; + virtual Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const = 0; }; diff --git a/sound/null.cpp b/sound/null.cpp index 00a5f5e488..556b96c14c 100644 --- a/sound/null.cpp +++ b/sound/null.cpp @@ -22,63 +22,41 @@ * $Id$ */ -#include "sound/musicplugin.h" -#include "sound/mpu401.h" +#include "sound/null.h" -/* NULL driver */ -class MidiDriver_NULL : public MidiDriver_MPU401 { -public: - int open() { return 0; } - void send(uint32 b) { } -}; +Common::Error NullMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { + *mididriver = new MidiDriver_NULL(); + return Common::kNoError; +} -// Plugin interface +MusicDevices NullMusicPlugin::getDevices() const { + MusicDevices devices; + devices.push_back(MusicDevice(this, "", MT_NULL)); + return devices; +} -class NullMusicPlugin : public MusicPluginObject { +class AutoMusicPlugin : public NullMusicPlugin { public: const char *getName() const { - return "No music"; + return _s("<default>"); } const char *getId() const { - return "null"; + return "auto"; } - MusicDevices getDevices() const; - Common::Error createInstance(MidiDriver **mididriver) const; }; -Common::Error NullMusicPlugin::createInstance(MidiDriver **mididriver) const { - *mididriver = new MidiDriver_NULL(); - - return Common::kNoError; -} - -MusicDevices NullMusicPlugin::getDevices() const { +MusicDevices AutoMusicPlugin::getDevices() const { MusicDevices devices; - // TODO: return a different music type? - devices.push_back(MusicDevice(this, "", MT_GM)); + devices.push_back(MusicDevice(this, "", MT_AUTO)); return devices; } -MidiDriver *MidiDriver_NULL_create() { - MidiDriver *mididriver; - - NullMusicPlugin p; - p.createInstance(&mididriver); - - return mididriver; -} - -#ifdef DISABLE_ADLIB -MidiDriver *MidiDriver_ADLIB_create() { - return MidiDriver_NULL_create(); -} -#endif - //#if PLUGIN_ENABLED_DYNAMIC(NULL) //REGISTER_PLUGIN_DYNAMIC(NULL, PLUGIN_TYPE_MUSIC, NullMusicPlugin); //#else + REGISTER_PLUGIN_STATIC(AUTO, PLUGIN_TYPE_MUSIC, AutoMusicPlugin); REGISTER_PLUGIN_STATIC(NULL, PLUGIN_TYPE_MUSIC, NullMusicPlugin); //#endif diff --git a/sound/null.h b/sound/null.h new file mode 100644 index 0000000000..d9343701fa --- /dev/null +++ b/sound/null.h @@ -0,0 +1,56 @@ +/* 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_NULL_H +#define SOUND_NULL_H + +#include "sound/musicplugin.h" +#include "sound/mpu401.h" +#include "common/translation.h" + +/* NULL driver */ +class MidiDriver_NULL : public MidiDriver_MPU401 { +public: + int open() { return 0; } + void send(uint32 b) { } +}; + + +// Plugin interface + +class NullMusicPlugin : public MusicPluginObject { +public: + virtual const char *getName() const { + return _s("No music"); + } + + virtual const char *getId() const { + return "null"; + } + + virtual MusicDevices getDevices() const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; +}; + +#endif diff --git a/sound/softsynth/adlib.cpp b/sound/softsynth/adlib.cpp index 6697cef646..ffb359e816 100644 --- a/sound/softsynth/adlib.cpp +++ b/sound/softsynth/adlib.cpp @@ -27,6 +27,7 @@ #include "common/util.h" #include "sound/fmopl.h" #include "sound/musicplugin.h" +#include "common/translation.h" #ifdef DEBUG_ADLIB static int tick; @@ -1586,7 +1587,7 @@ void MidiDriver_ADLIB::adlib_note_on(int chan, byte note, int mod) { class AdLibEmuMusicPlugin : public MusicPluginObject { public: const char *getName() const { - return "AdLib Emulator"; + return _s("AdLib Emulator"); } const char *getId() const { @@ -1594,7 +1595,7 @@ public: } MusicDevices getDevices() const; - Common::Error createInstance(MidiDriver **mididriver) const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; }; MusicDevices AdLibEmuMusicPlugin::getDevices() const { @@ -1603,21 +1604,12 @@ MusicDevices AdLibEmuMusicPlugin::getDevices() const { return devices; } -Common::Error AdLibEmuMusicPlugin::createInstance(MidiDriver **mididriver) const { +Common::Error AdLibEmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { *mididriver = new MidiDriver_ADLIB(g_system->getMixer()); return Common::kNoError; } -MidiDriver *MidiDriver_ADLIB_create() { - MidiDriver *mididriver; - - AdLibEmuMusicPlugin p; - p.createInstance(&mididriver); - - return mididriver; -} - //#if PLUGIN_ENABLED_DYNAMIC(ADLIB) //REGISTER_PLUGIN_DYNAMIC(ADLIB, PLUGIN_TYPE_MUSIC, AdLibEmuMusicPlugin); //#else diff --git a/sound/softsynth/fluidsynth.cpp b/sound/softsynth/fluidsynth.cpp index c3bd782cc1..fcb4591a20 100644 --- a/sound/softsynth/fluidsynth.cpp +++ b/sound/softsynth/fluidsynth.cpp @@ -230,7 +230,7 @@ public: } MusicDevices getDevices() const; - Common::Error createInstance(MidiDriver **mididriver) const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; }; MusicDevices FluidSynthMusicPlugin::getDevices() const { @@ -239,21 +239,12 @@ MusicDevices FluidSynthMusicPlugin::getDevices() const { return devices; } -Common::Error FluidSynthMusicPlugin::createInstance(MidiDriver **mididriver) const { +Common::Error FluidSynthMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { *mididriver = new MidiDriver_FluidSynth(g_system->getMixer()); return Common::kNoError; } -MidiDriver *MidiDriver_FluidSynth_create() { - MidiDriver *mididriver; - - FluidSynthMusicPlugin p; - p.createInstance(&mididriver); - - return mididriver; -} - //#if PLUGIN_ENABLED_DYNAMIC(FLUIDSYNTH) //REGISTER_PLUGIN_DYNAMIC(FLUIDSYNTH, PLUGIN_TYPE_MUSIC, FluidSynthMusicPlugin); //#else diff --git a/sound/softsynth/mt32.cpp b/sound/softsynth/mt32.cpp index 612dce06b0..95263a040d 100644 --- a/sound/softsynth/mt32.cpp +++ b/sound/softsynth/mt32.cpp @@ -39,6 +39,7 @@ #include "common/system.h" #include "common/util.h" #include "common/archive.h" +#include "common/translation.h" #include "graphics/fontman.h" #include "graphics/surface.h" @@ -323,7 +324,7 @@ int MidiDriver_MT32::open() { } _initialising = true; - drawMessage(-1, "Initialising MT-32 Emulator"); + drawMessage(-1, _s("Initialising MT-32 Emulator")); if (!_synth->open(prop)) return MERR_DEVICE_NOT_AVAILABLE; _initialising = false; @@ -537,7 +538,7 @@ void MidiDriver_ThreadedMT32::onTimer() { class MT32EmuMusicPlugin : public MusicPluginObject { public: const char *getName() const { - return "MT-32 Emulator"; + return _s("MT-32 Emulator"); } const char *getId() const { @@ -545,7 +546,7 @@ public: } MusicDevices getDevices() const; - Common::Error createInstance(MidiDriver **mididriver) const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; }; MusicDevices MT32EmuMusicPlugin::getDevices() const { @@ -554,23 +555,13 @@ MusicDevices MT32EmuMusicPlugin::getDevices() const { return devices; } -Common::Error MT32EmuMusicPlugin::createInstance(MidiDriver **mididriver) const { - *mididriver = new MidiDriver_MT32(g_system->getMixer()); - - return Common::kNoError; -} - -MidiDriver *MidiDriver_MT32_create() { - // HACK: It will stay here until engine plugin loader overhaul +Common::Error MT32EmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { if (ConfMan.hasKey("extrapath")) SearchMan.addDirectory("extrapath", ConfMan.get("extrapath")); - MidiDriver *mididriver; - - MT32EmuMusicPlugin p; - p.createInstance(&mididriver); + *mididriver = new MidiDriver_MT32(g_system->getMixer()); - return mididriver; + return Common::kNoError; } //#if PLUGIN_ENABLED_DYNAMIC(MT32) diff --git a/sound/softsynth/pcspk.cpp b/sound/softsynth/pcspk.cpp index 396d9328f1..bdf9f112e8 100644 --- a/sound/softsynth/pcspk.cpp +++ b/sound/softsynth/pcspk.cpp @@ -24,6 +24,7 @@ */ #include "sound/softsynth/pcspk.h" +#include "sound/null.h" namespace Audio { @@ -128,3 +129,59 @@ int8 PCSpeaker::generateTriangle(uint32 x, uint32 oscLength) { } } // End of namespace Audio + + +// Plugin interface +// (This can only create a null driver since pc speaker support is not part of the +// midi driver architecture. But we need the plugin for the options menu in the launcher +// and for MidiDriver::detectDevice() which is more or less used by all engines.) + +class PCSpeakerMusicPlugin : public NullMusicPlugin { +public: + const char *getName() const { + return _s("PC Speaker Emulator"); + } + + const char *getId() const { + return "pcspk"; + } + + MusicDevices getDevices() const; +}; + +MusicDevices PCSpeakerMusicPlugin::getDevices() const { + MusicDevices devices; + devices.push_back(MusicDevice(this, "", MT_PCSPK)); + return devices; +} + +class PCjrMusicPlugin : public NullMusicPlugin { +public: + const char *getName() const { + return _s("IBM PCjr Emulator"); + } + + const char *getId() const { + return "pcjr"; + } + + MusicDevices getDevices() const; +}; + +MusicDevices PCjrMusicPlugin::getDevices() const { + MusicDevices devices; + devices.push_back(MusicDevice(this, "", MT_PCJR)); + return devices; +} + +//#if PLUGIN_ENABLED_DYNAMIC(PCSPK) + //REGISTER_PLUGIN_DYNAMIC(PCSPK, PLUGIN_TYPE_MUSIC, PCSpeakerMusicPlugin); +//#else + REGISTER_PLUGIN_STATIC(PCSPK, PLUGIN_TYPE_MUSIC, PCSpeakerMusicPlugin); +//#endif + +//#if PLUGIN_ENABLED_DYNAMIC(PCJR) + //REGISTER_PLUGIN_DYNAMIC(PCJR, PLUGIN_TYPE_MUSIC, PCjrMusicPlugin); +//#else + REGISTER_PLUGIN_STATIC(PCJR, PLUGIN_TYPE_MUSIC, PCjrMusicPlugin); +//#endif diff --git a/sound/softsynth/sid.cpp b/sound/softsynth/sid.cpp index e0dfd2efc0..d600ac28f5 100644 --- a/sound/softsynth/sid.cpp +++ b/sound/softsynth/sid.cpp @@ -506,7 +506,7 @@ Filter::Filter() { + sizeof(f0_points_6581)/sizeof(*f0_points_6581) - 1, PointPlotter<sound_sample>(f0_6581), 1.0); - mixer_DC = -0xfff*0xff/18 >> 7; + mixer_DC = (-0xfff*0xff/18) >> 7; f0 = f0_6581; f0_points = f0_points_6581; diff --git a/sound/softsynth/ym2612.cpp b/sound/softsynth/ym2612.cpp index e337bc4ab9..08331c6244 100644 --- a/sound/softsynth/ym2612.cpp +++ b/sound/softsynth/ym2612.cpp @@ -27,6 +27,7 @@ #include "sound/softsynth/ym2612.h" #include "common/util.h" #include "sound/musicplugin.h" +#include "common/translation.h" //////////////////////////////////////// // @@ -758,7 +759,7 @@ void MidiDriver_YM2612::removeLookupTables() { class TownsEmuMusicPlugin : public MusicPluginObject { public: const char *getName() const { - return "FM Towns Emulator"; + return _s("FM Towns Emulator"); } const char *getId() const { @@ -766,7 +767,7 @@ public: } MusicDevices getDevices() const; - Common::Error createInstance(MidiDriver **mididriver) const; + Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const; }; MusicDevices TownsEmuMusicPlugin::getDevices() const { @@ -775,21 +776,12 @@ MusicDevices TownsEmuMusicPlugin::getDevices() const { return devices; } -Common::Error TownsEmuMusicPlugin::createInstance(MidiDriver **mididriver) const { +Common::Error TownsEmuMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const { *mididriver = new MidiDriver_YM2612(g_system->getMixer()); return Common::kNoError; } -MidiDriver *MidiDriver_YM2612_create() { - MidiDriver *mididriver; - - TownsEmuMusicPlugin p; - p.createInstance(&mididriver); - - return mididriver; -} - //#if PLUGIN_ENABLED_DYNAMIC(TOWNS) //REGISTER_PLUGIN_DYNAMIC(TOWNS, PLUGIN_TYPE_MUSIC, TownsEmuMusicPlugin); //#else diff --git a/tools/convbdf.c b/tools/convbdf.c index 4341eac2e7..ad0d9d2373 100644 --- a/tools/convbdf.c +++ b/tools/convbdf.c @@ -38,12 +38,12 @@ #include <time.h> int READ_UINT16(void *addr) { - unsigned char *buf = addr; + unsigned char *buf = (unsigned char *)addr; return (buf[0] << 8) | buf[1]; } void WRITE_UINT16(void *addr, int value) { - unsigned char *buf = addr; + unsigned char *buf = (unsigned char *)addr; buf[0] = (value >> 8) & 0xFF; buf[1] = value & 0xFF; } @@ -611,7 +611,7 @@ int bdf_read_bitmaps(FILE *fp, struct font* pf) { /* determine whether font doesn't require encode table*/ l = 0; for (i = 0; i < pf->size; ++i) { - if (pf->offset[i] != l) { + if (pf->offset[i] != (unsigned long)l) { encodetable = 1; break; } @@ -648,7 +648,7 @@ int bdf_read_bitmaps(FILE *fp, struct font* pf) { /* reallocate bits array to actual bits used*/ if (ofs < pf->bits_size) { - pf->bits = realloc(pf->bits, ofs * sizeof(bitmap_t)); + pf->bits = (bitmap_t *)realloc(pf->bits, ofs * sizeof(bitmap_t)); pf->bits_size = ofs; } else { diff --git a/tools/create_msvc/create_msvc.cpp b/tools/create_msvc/create_msvc.cpp index a78c9c46a1..71cc35f8e2 100644 --- a/tools/create_msvc/create_msvc.cpp +++ b/tools/create_msvc/create_msvc.cpp @@ -838,11 +838,14 @@ const Feature s_features[] = { { "mpeg2", "USE_MPEG2", "libmpeg2.lib", false, "mpeg2 codec for cutscenes" }, // ScummVM feature flags - { "scalers", "USE_SCALERS", "", true, "Scalers" }, - { "hqscalers", "USE_HQ_SCALERS", "", true, "HQ scalers" }, - { "16bit", "USE_RGB_COLOR", "", true, "16bit color support" }, - { "mt32emu", "USE_MT32EMU", "", true, "integrated MT-32 emulator" }, - { "nasm", "USE_NASM", "", true, "IA-32 assembly support" }, // This feature is special in the regard, that it needs additional handling. + { "scalers", "USE_SCALERS", "", true, "Scalers" }, + { "hqscalers", "USE_HQ_SCALERS", "", true, "HQ scalers" }, + { "16bit", "USE_RGB_COLOR", "", true, "16bit color support" }, + { "mt32emu", "USE_MT32EMU", "", true, "integrated MT-32 emulator" }, + { "nasm", "USE_NASM", "", true, "IA-32 assembly support" }, // This feature is special in the regard, that it needs additional handling. + { "translation", "USE_TRANSLATION", "", true, "Translation support" }, + { "langdetect", "USE_DETECTLANG", "", true, "System language detection support" } // This feature actually depends on "translation", there + // is just no current way of properly detecting this... }; } // End of anonymous namespace diff --git a/tools/credits.pl b/tools/credits.pl index bff1251f7a..02a42c12cc 100755 --- a/tools/credits.pl +++ b/tools/credits.pl @@ -854,6 +854,31 @@ begin_credits("Credits"); add_person("Johannes Schickel", "LordHoto", ""); end_section(); end_section(); + + begin_section("Translations"); + begin_persons(); + add_person("Thierry Crozat", "criezy", "Translation Lead"); + end_persons(); + begin_section("Catalan"); + add_person("Jordi Vilalta Prat", "jvprat", ""); + end_section(); + begin_section("French"); + add_person("Thierry Crozat", "criezy", ""); + end_section(); + begin_section("German"); + add_person("Simon Sawatzki", "SimSaw", ""); + add_person("Lothar Serra Mari", "Lothar93", ""); + end_section(); + begin_section("Hungarian"); + add_person("Alex Bevilacqua", "", ""); + end_section(); + begin_section("Italian"); + add_person("Matteo Angelino", "Maff", ""); + end_section(); + begin_section("Russian"); + add_person("Eugene Sandulenko", "sev", ""); + end_section(); + end_section(); begin_section("Websites (design)"); begin_persons(); @@ -922,7 +947,7 @@ begin_credits("Credits"); add_person("Ravi I.", "", "SCI0 sound resource specification"); add_person("Ruediger Hanke", "", "Port to the MorphOS platform"); add_person("Rune Orsval", "", "Configuration file editor"); - add_person("Rickard Lind", "", "MT32->GM MIDI mapping magic, sound research"); + add_person("Rickard Lind", "", "MT-32->GM MIDI mapping magic, sound research"); add_person("Rink Springer", "", "Port to the DOS platform, several bug fixes"); add_person("Robey Pointer", "", "Bug tracking system hosting"); add_person("Sergey Lapin", "", "Port of Carl's type 2 decompression code"); @@ -933,8 +958,8 @@ begin_credits("Credits"); add_person("Sean Terrell", "", ""); end_persons(); add_paragraph("Special thanks to Prof. Dr. Gary Nutt ". - "for allowing the FreeSCI VM extension as a ". - "course project in his Advanced OS course."); + "for allowing the FreeSCI VM extension as a ". + "course project in his Advanced OS course."); add_paragraph("Special thanks to Bob Heitman and Corey Cole for their support of FreeSCI."); end_section(); diff --git a/tools/make-scumm-fontdata.c b/tools/make-scumm-fontdata.c index f251a22b80..991d49831a 100644 --- a/tools/make-scumm-fontdata.c +++ b/tools/make-scumm-fontdata.c @@ -821,7 +821,7 @@ static const unsigned char spanishCharsetDataV2[] = { unsigned char *specialCharsetData = NULL; int numSpecialChars = 0; -void compressCharset(const unsigned char *data, char *var, char *name) { +void compressCharset(const unsigned char *data, const char *var, const char *name) { int i; printf("// %s\n", name); diff --git a/tools/md5table.c b/tools/md5table.c index 6823607b27..7d76b7541d 100644 --- a/tools/md5table.c +++ b/tools/md5table.c @@ -77,6 +77,7 @@ typedef struct { * common/util.h). */ static const StringMap platformMap[] = { + { "2gs", "kPlatformApple2GS" }, { "3DO", "kPlatform3DO" }, { "Amiga", "kPlatformAmiga" }, { "Atari", "kPlatformAtariST" }, diff --git a/tools/module.mk b/tools/module.mk index 896a2e504b..2c62e427ea 100644 --- a/tools/module.mk +++ b/tools/module.mk @@ -65,7 +65,6 @@ md5scumm: tools/md5table$(EXEEXT) tools/md5table$(EXEEXT) --c++ < $(srcdir)/tools/scumm-md5.txt > $(srcdir)/engines/scumm/scumm-md5.h cp $(srcdir)/tools/scumm-md5.txt $(srcdir)/../../web/trunk/data/scumm-md5.txt - # # Rules which automatically and implicitly rebuild the credits and # MD5 tables when needed. diff --git a/tools/po2c b/tools/po2c new file mode 100755 index 0000000000..9dbc5e0fb7 --- /dev/null +++ b/tools/po2c @@ -0,0 +1,260 @@ +#!/usr/bin/perl + +# +# po2c - Converts .po files to C code +# +# Copyright (C) 2004 Angel Ortega <angel@triptico.com> +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# http://www.triptico.com +# + +$VERSION = "1.0.2-scummvm"; + +if(scalar(@ARGV) == 0) +{ + print "Usage: po2c {po file[s]}\n"; + exit 1; +} + +%msgs = (); +%msgids = (); + +# stage 1: loading + +# arguments are .po files +foreach my $f (@ARGV) +{ + my ($lang); + my ($langDesc); + + next unless(($lang) = ($f =~ /([^\/]+)\.po$/)); + + if(open F, $f) + { + my ($msgid, $val, %a); + + while(<F>) + { + chomp; + + # ignore blank lines or comments + next if /^$/ or /^#/; + + if(/^msgid\s+\"(.*)\"\s*$/) + { + # store previous msgid + if(defined($msgid)) + { + $a{$msgid} = $val; + $msgids{$msgid} ++; + } + + # start of msgid + $val = $1; + } + elsif(/^msgstr\s+\"(.*)\"\s*$/) + { + # store previous msgid + $msgid = $val; + + # start of msgstr + $val = $1; + } + elsif(/^\"(.*)\"\s*$/) + { + # add to current value + $val .= $1; + } + } + + # store previous msgid + if(defined($msgid)) + { + $a{$msgid} = $val; + $msgids{$msgid} ++; + } + + close F; + + # add to the global message pool + $msgs{$lang} = \%a; + } +} + +# stage 2: convert the data + +# stores all sorted msgids into @msgids +@msgids = sort(keys(%msgids)); + +# travels again, storing indexes into %msgids +for(my $n = 0;$n < scalar(@msgids);$n++) +{ + $msgids{$msgids[$n]} = $n; +} + +# stage 3: dump as C++ code + +print "// generated by po2c $VERSION - Do not modify\n\n"; + +# dump first the msgid array +print "static const char * const _messageIds[] = {\n"; + +for(my $n = 0;$n < scalar(@msgids);$n++) +{ + print "\t/* $n */ \"" . $msgids[$n] . "\",\n"; +} + +print "\tNULL\n};\n\n"; + +# dump the lang structure +print "struct PoMessageEntry {\n"; +print "\tint msgid;\n"; +print "\tconst char *msgstr;\n"; +print "};\n\n"; + +# dump now each language + +foreach my $l (keys(%msgs)) +{ + print "static const PoMessageEntry _translation_${l}\[\] = {\n"; + + # get the translation table for the language $l + my ($m) = $msgs{$l}; + +# while (my ($msgstr, $msgid) = each (%$m)) + foreach my $msgid (sort(keys(%$m))) + { + my ($msgstr) = ""; + + # make it 7-bit safe + foreach $c (split(//, $m->{$msgid})) { + if (ord($c) > 0x7f) { + $msgstr .= sprintf("\\%o", ord($c)); + } else { + $msgstr .= $c; + } + } + + print "\t{ " . $msgids{$msgid} . ", \"" . $msgstr . "\" },\n" + if $msgstr; + } + + print "\t{ -1, NULL }\n};\n\n"; +} + +# finally, dump the languages + +print "struct PoLangEntry {\n"; +print "\tconst char *lang;\n"; +print "\tconst char *charset;\n"; +print "\tconst PoMessageEntry *msgs;\n"; +print "};\n\n"; +print "const PoLangEntry _translations[] = {\n"; + +foreach my $l (keys(%msgs)) +{ + $header = $msgs{$l}->{""}; + $header =~ /charset=([^\\]+)/; + $charset = $1; + print "\t{ \"" . $l . "\", \"" . $charset . "\", _translation_${l} },\n"; +} + +print "\t{ NULL, NULL, NULL }\n};\n\n"; + +print "// code\n"; +print << 'EOF'; + +static const PoMessageEntry *_currentTranslation = NULL; +static int _currentTranslationMessageEntryCount = 0; +static const char *_currentTranslationCharset = NULL; + +void po2c_setlang(const char *lang) { + _currentTranslation = NULL; + _currentTranslationMessageEntryCount = 0; + _currentTranslationCharset = NULL; + + // if lang is NULL or "", deactivate it + if (lang == NULL || *lang == '\0') + return; + + // searches for a valid language array + for (int i = 0; _currentTranslation == NULL && _translations[i].lang != NULL; ++i) { + if (strcmp(lang, _translations[i].lang) == 0) { + _currentTranslation = _translations[i].msgs; + _currentTranslationCharset = _translations[i].charset; + } + } + + // try partial searches + for (int i = 0; _currentTranslation == NULL && _translations[i].lang != NULL; ++i) { + if (strncmp(lang, _translations[i].lang, 2) == 0) { + _currentTranslation = _translations[i].msgs; + _currentTranslationCharset = _translations[i].charset; + } + } + + // if found, count entries + if (_currentTranslation != NULL) { + for (const PoMessageEntry *m = _currentTranslation; m->msgid != -1; ++m) + ++_currentTranslationMessageEntryCount; + } +} + +const char *po2c_gettext(const char *msgid) { + // if no language is set or msgid is empty, return msgid as is + if (_currentTranslation == NULL || *msgid == '\0') + return msgid; + + // binary-search for the msgid + int leftIndex = 0; + int rightIndex = _currentTranslationMessageEntryCount - 1; + + while (rightIndex >= leftIndex) { + const int midIndex = (leftIndex + rightIndex) / 2; + const PoMessageEntry * const m = &_currentTranslation[midIndex]; + + const int compareResult = strcmp(msgid, _messageIds[m->msgid]); + + if (compareResult == 0) + return m->msgstr; + else if (compareResult < 0) + rightIndex = midIndex - 1; + else + leftIndex = midIndex + 1; + } + + return msgid; +} + +const char *po2c_getcharset(void) { + if (_currentTranslationCharset) + return _currentTranslationCharset; + else + return "ASCII"; +} + +int po2c_getnumlangs(void) { + return ARRAYSIZE(_translations) - 1; +} + +const char *po2c_getlang(const int num) { + assert(num < ARRAYSIZE(_translations)); + return _translations[num].lang; +} +EOF + +exit 0; diff --git a/tools/scumm-md5.txt b/tools/scumm-md5.txt index 0637c386d7..c3e48d6c5a 100644 --- a/tools/scumm-md5.txt +++ b/tools/scumm-md5.txt @@ -60,7 +60,7 @@ maniac Maniac Mansion 7f45ddd6dbfbf8f80c0c0efea4c295bc 1972 en DOS V1 V1 - Fingolfin - 17f7296f63c78642724f057fd8e736a7 -1 gb NES NES - + 17f7296f63c78642724f057fd8e736a7 2082 gb NES NES - 91d5db93187fab54d823f73bd6441cb6 -1 us NES NES - 1c7e7db2cfab1ad62746ab680a634204 -1 fr NES NES - 3a5ec90d556d4920976c5578bfbfaf79 -1 de NES NES - @@ -172,10 +172,10 @@ loom Loom 5d88b9d6a88e6f8e90cded9d01b7f082 8307 en DOS VGA VGA CD Version v1.0 from 10. Feb 92 (Talkie) Peter Eckerlein, Fingolfin - c5d10e190d4b4d59114b824f2fdbd00e -1 en FM-TOWNS FM-TOWNS - - dhewg, Andrea Petrucci + c5d10e190d4b4d59114b824f2fdbd00e 7540 en FM-TOWNS FM-TOWNS - - dhewg, Andrea Petrucci 31b8fda4c8c7413fa6b39997e776eba4 -1 jp FM-TOWNS FM-TOWNS - - khalek, Andrea Petrucci - 0aa050f4ad79402fbe9c4f78fb8ac494 -1 en PC-Engine PC-Engine - - Kirben + 0aa050f4ad79402fbe9c4f78fb8ac494 6532 en PC-Engine PC-Engine - - Kirben 79b05f628586837e7166e82b2279bb50 -1 jp PC-Engine PC-Engine - - clone2727 5a35e36fd777e9c37a49c5b2faca52f9 6108 en DOS EGA EGA Demo non-interactive Fingolfin @@ -189,7 +189,7 @@ monkey The Secret of Monkey Island 49210e124e4c2b30f1290a9ef6306301 8357 en DOS EGA EGA 8 disk v1.0, 9/18/90 Fingolfin 1dd3c11ea4439adfe681e4e405b624e1 -1 fr DOS EGA EGA 8 disk Andrea Petrucci - fc6b6148e80d67939d9a18697c0f626a -1 de DOS EGA EGA 8 disk ghoostkilla + fc6b6148e80d67939d9a18697c0f626a 8367 de DOS EGA EGA 8 disk ghoostkilla 910e31cffb28226bd68c569668a0d6b4 -1 es DOS EGA EGA 8 disk Andrea Petrucci 1d05cd189e4908f79b57e78a4402f292 -1 en DOS EGA EGA 4 disk Andrea Petrucci ce6a4cef315b20fef58a95bc40a2d8d3 -1 fr DOS EGA EGA 4 disk Matthieu Milan @@ -225,12 +225,12 @@ monkey The Secret of Monkey Island c13225cb1bbd3bc9fe578301696d8021 -1 en SEGA SEGA - - 057c9b456dedcc4d71b991a3072a20b3 9465 jp SEGA SEGA - - GloKidd - 8eb84cee9b429314c7f0bdcf560723eb -1 en FM-TOWNS FM-TOWNS - - Paul Priest, Andrea Petrucci + 8eb84cee9b429314c7f0bdcf560723eb 9925 en FM-TOWNS FM-TOWNS - - Paul Priest, Andrea Petrucci e17db1ddf91b39ca6bbc8ad3ed19e883 -1 jp FM-TOWNS FM-TOWNS - - Paul Priest, Andrea Petrucci 71523b539491527d9860f4407faf0411 7607 en DOS Demo EGA Demo - Fingolfin 771bc18ec6f93837b839c992b211904b -1 de DOS Demo EGA Demo - khalek - 54a936ad06161ff7bfefcb96200f7bff -1 en Amiga VGA VGA Demo - khalek + 54a936ad06161ff7bfefcb96200f7bff 7617 en Amiga VGA VGA Demo - khalek pass Passport to Adventure e6cd81b25ab1453a8a6d3482118c391e 7857 en DOS - - v1.0 9/14/90 Fingolfin @@ -279,8 +279,9 @@ atlantis Indiana Jones and the Fate of Atlantis 1a6e5ae2777a6a33f06ffc0226210934 -1 en Mac - CD - Scott Summers 2d9d46f23cb07bbc90b8ad464d3e4ff8 -1 en Mac - CD Mac bundle Joachim Eberhard 8e9417564f33790815445b2136efa667 11915 jp Mac - CD - Petr Maruska + e8d0697906e53fee8b7e9f5652696da8 11915 jp DOS - CD - Petr Maruska, tracker #3017219 - c7be10f775404fd9785a8b92a06d240c -1 en FM-TOWNS - - - dhewg, Andrea Petrucci + c7be10f775404fd9785a8b92a06d240c 12030 en FM-TOWNS - - - dhewg, Andrea Petrucci 4d34042713958b971cb139fba4658586 -1 jp FM-TOWNS - - - Andrea Petrucci 035deab53b47bc43abc763560d0f8d4b -1 en DOS Floppy Demo - @@ -325,7 +326,7 @@ samnmax Sam & Max Hit the Road 0f6f2e716ba896a44e5059bba1de7ca9 -1 it All? - CD - Andrea Petrucci 4ba7fb331296c283e73d8f5b2096e551 -1 es All? - CD - Andrea Petrucci d43352a805d78b5f4936c6d7779bf575 -1 ru DOS - CD - - 166553538ff320c69edafeee29525419 -1 en Mac - CD Mac bundle Joachim Eberhard + 166553538ff320c69edafeee29525419 199195304 en Mac - CD Mac bundle Joachim Eberhard 3a5d13675e9a23aedac0bac7730f0ac1 -1 fr Mac - CD Mac bundle ThierryFR c3196c5349e53e387aaff1533d95e53a -1 en DOS Floppy Demo - @@ -386,7 +387,7 @@ football Backyard Football 7fc6cdb46b4c9d384c52327f4bca6416 -1 en All - - - sev 425205754fa749f4f0b0dd9d09fa45fd -1 en All - Demo - Joachim Eberhard - 5bd335265a61caa3d78956ad9f88ba23 -1 en All - Demo - sev + 5bd335265a61caa3d78956ad9f88ba23 23135 en All - Demo - sev football2002 Backyard Football 2002 a095616d2d23ccf43b8e257711202cba -1 en All - - - clone2727 @@ -484,6 +485,12 @@ freddi Freddi Fish 1: The Case of the Missing Kelp Seeds a197a87ae77f3b3333f09a7a2c448fe2 -1 en Windows HE 99 Updated - Jonathan af2bd1a43b50b55915d87994e093203d 34829 de Windows HE 99 Updated - Lightkey 57a5cfec9ef231a007043cc1917e8988 -1 en Wii HE 100 - - sanguinehearts + 56b5922751be7ffd771b38dda56b028b 34837 nl Wii HE 100 - - George Kormendi + 3ae7f002d9256b8bdf76aaf8a3a069f8 34837 gb Wii HE 100 - - George Kormendi + 30d1903b0715759af064be2127381cd0 34837 de Wii HE 100 - - George Kormendi + 4afb734df8315ee412669c812d4cf0a1 34837 fr Wii HE 100 - - George Kormendi + a59a438cb182124c30c4447d8ed469e9 34837 nb Wii HE 100 - - George Kormendi + 880c5ca5b944648b3f8b03feb41705a8 34837 se Wii HE 100 - - George Kormendi c7c492a107ec520d7a7943037d0ca54a -1 nl Windows HE 71 Demo - DarthBo 084ed0fa98a6d1e9368d67fe9cfbd417 -1 en Windows HE 71 Demo - khalek @@ -557,7 +564,7 @@ freddicove Freddi Fish 5: The Case of the Creature of Coral Cove 4ce2d5b355964bbcb5e5ce73236ef868 -1 ru Windows HE 100 - - sev 6b257bb2827dd894b8109a50a1a18b5a -1 nl All HE 100 Demo - Kirben, sev - 45082a5c9f42ba14dacfe1fdeeba819d -1 en All HE 100 Demo - sev + 45082a5c9f42ba14dacfe1fdeeba819d 18422 en All HE 100 Demo - sev maze Freddi Fish and Luther's Maze Madness 4f04b321a95d4315ce6d65f8e1dd0368 -1 us All HE 80 - - Kirben @@ -588,7 +595,7 @@ airport Let's Explore the Airport with Buzzy 7ea2da67ebabea4ac20cee9f4f9d2934 -1 en Mac - Demo - khalek 8ffd618a776a4c0d8922bb28b09f8ce8 -1 en Windows - Demo - khalek - e144f5f49d9241d2a9dee2576b3d09cb -1 en Windows - Demo - khalek + e144f5f49d9241d2a9dee2576b3d09cb 51152 en Windows - Demo - khalek 86c9902b7bec1a17926d4dae85beaa45 -1 en Windows HE 71 Demo - khalek farm Let's Explore the Farm with Buzzy @@ -601,7 +608,7 @@ farm Let's Explore the Farm with Buzzy 39fd6db10d0222d817025c4d3346e3b4 -1 en Mac - Demo - Joachim Eberhard bf8b52fdd9a69c67f34e8e9fec72661c -1 en Windows HE 71 Demo - khalek, sev 0557df19f046a84c2fdc63507c6616cb -1 nl Windows HE 72 Demo - adutchguy - 8d479e36f35e80257dfc102cf4b8a912 -1 en Windows HE 72 Demo - khalek, sev + 8d479e36f35e80257dfc102cf4b8a912 34333 en Windows HE 72 Demo - khalek, sev jungle Let's Explore the Jungle with Buzzy 659942b9a6b519f123a13cca3c333a13 -1 en Mac - - - Joachim Eberhard @@ -654,13 +661,13 @@ pajama3 Pajama Sam 3: You Are What You Eat From Your Head to Your Feet f08145577e4f13584cc90b3d6e9caa55 -1 nl All - Demo - joostp a654fb60c3b67d6317a7894ffd9f25c5 -1 us All - Demo - sev a9f2f04b1ecaab9495b59befffe9bf88 -1 us All - Demo - sev - 0c45eb4baff0c12c3d9dfa889c8070ab -1 de All - Demo - Joachim Eberhard + 0c45eb4baff0c12c3d9dfa889c8070ab 13884 de All - Demo - Joachim Eberhard 4fe6a2e8df3c4536b278fdd2fbcb181e -1 en Windows - Mini Game - Trekky 679855cf61932f9bf995c8f3677380ed -1 fr Windows - Demo - Mevi c8c5baadcbfc8d0372ed4335abace8a7 -1 fr Windows - Demo - Mevi 784b499c98d07260a30952685758636b 13911 de Windows - Demo - George Kormendi 3e48298920fab9b7aec5a971e1bd1fab -1 gb Windows - Demo - eriktorbjorn - cf90b4db5486ef798db78fe6fbf897e5 -1 us Windows - Demo - khalek + cf90b4db5486ef798db78fe6fbf897e5 13902 us Windows - Demo - khalek pjgames Pajama Sam: Games to Play on Any Day 8a484262363a8e18be87112454f1456b -1 us All - - - Kirben @@ -752,10 +759,10 @@ puttzoo Putt-Putt Saves the Zoo 3a3e592b074f595489f7f11e150c398d -1 us Windows HE 99 Updated - Adrian c5cc7cba02a2fbd539c4439e775b0536 43470 de Windows HE 99 Updated - Lightkey - 3486ede0f904789267d4bcc5537a46d4 -1 en Mac - Demo - khalek + 3486ede0f904789267d4bcc5537a46d4 14337 en Mac - Demo - khalek d220d154aafbfa12bd6f3ab1b2dae420 -1 de Mac - Demo - Joachim Eberhard aa81aa6d5545ce172fdba81f2e2f9d36 -1 nl Windows - Demo - DarthBo - de4efb910210736813c9a1185384bace -1 en Windows HE 72 Demo - khalek + de4efb910210736813c9a1185384bace 14337 en Windows HE 72 Demo - khalek f3d55aea441e260e9e9c7d2a187097e0 14337 en Windows - Demo - khalek 65fa23d6884e8ca23d5d2406d70de7e8 -1 fr Windows - Demo - gist974 2a446817ffcabfef8716e0c456ecaf81 -1 de Windows - Demo - Joachim Eberhard @@ -834,7 +841,7 @@ spyfox2 SPY Fox 2: Some Assembly Required 90e2f0af4f779629695c6394a65bb702 -1 fr All - - - gist974, ThierryFR bc4700bc0e12879f6d25d14d6be6cfdd -1 de All - - - Joachim Eberhard cea91e3dd47f2518ea418e41611aa77f -1 ru All - - - sev - 9fd66fb3b04703bd50da4356e4202558 -1 en Mac - - - pix_climber + 9fd66fb3b04703bd50da4356e4202558 51295 en Mac - - - pix_climber 71fe97c3108678cf604f14abe342341b -1 nl Windows - - - adutchguy 1c792d28376d45e145cb916bca0400a2 -1 nl All - Demo - joostp @@ -853,7 +860,7 @@ spyozon SPY Fox 3: Operation Ozone 7015b059ab72cff3a0ef9fb4d5e9889d -1 de Windows - - - andy482 be39a5d4db60e8aa736b9086778cb45c -1 gb Windows - - - - ebd0b2c8a387f18887282afe6cad894a -1 en All - Demo - Kirben + ebd0b2c8a387f18887282afe6cad894a 15317 en All - Demo - Kirben a99c39ba65b6086be28aef576da69595 -1 fr Windows - Demo - Mevi 65563295c3a06493351870f20a1630cf 5235008 All All HE CUP Preview - sev |